diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 76a597f..47bb4f0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,8 +15,18 @@ repos: - id: check-yaml - id: debug-statements - id: end-of-file-fixer + - id: mixed-line-ending + - id: no-commit-to-branch - id: trailing-whitespace + - repo: https://github.com/crate-ci/typos + rev: v1.32.0 + hooks: + - id: typos + args: [] + types_or: + - python + - repo: https://github.com/asottile/pyupgrade rev: v3.20.0 hooks: diff --git a/README.md b/README.md index e5f1f01..3056e52 100644 --- a/README.md +++ b/README.md @@ -289,8 +289,8 @@ In your model : ``` python class DbState(models.Model): - id = models.CharField(primary_key=True, max_length=50) - label = models.CharField(max_length=255) + id = models.CharField(primary_key=True) + label = models.CharField() def __str__(self): return self.label diff --git a/django_fsm/models.py b/django_fsm/models.py deleted file mode 100644 index 41eb870..0000000 --- a/django_fsm/models.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -Empty file to mark package as valid django application. -""" diff --git a/pyproject.toml b/pyproject.toml index 6c983ad..557d507 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,9 +66,8 @@ extend-ignore = [ "B", "PTH", "ANN", # Missing type annotation + "S101", # Use of `assert` detected "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "PT", # Use a regular `assert` instead of unittest-style - "DJ008", # Model does not define `__str__` method "ARG001", # Unused function argument "ARG002", # Unused method argument "TRY002", # Create your own exception @@ -84,6 +83,10 @@ fixable = [ "RUF100", # Unused `noqa` directive ] +[tool.ruff.lint.extend-per-file-ignores] +"tests/*" = [ + "DJ008", # Model does not define `__str__` method +] [tool.ruff.lint.isort] force-single-line = true diff --git a/tests/testapp/models.py b/tests/testapp/models.py index 29302f8..f7f592e 100644 --- a/tests/testapp/models.py +++ b/tests/testapp/models.py @@ -20,7 +20,7 @@ def draft(self): pass @transition(field=state, source=["new", "draft"], target="dept") - def to_approvement(self): + def submitted(self): pass @transition(field=state, source="dept", target="dean") @@ -53,7 +53,7 @@ def draft(self): pass @transition(field=state, source=["new", "draft"], target="dept") - def to_approvement(self): + def submitted(self): pass @transition(field=state, source="dept", target="dean") diff --git a/tests/testapp/tests/test_abstract_inheritance.py b/tests/testapp/tests/test_abstract_inheritance.py index 5b89cd2..1243ad4 100644 --- a/tests/testapp/tests/test_abstract_inheritance.py +++ b/tests/testapp/tests/test_abstract_inheritance.py @@ -42,20 +42,20 @@ def setUp(self): self.model = InheritedFromAbstractModel() def test_known_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" - self.assertTrue(can_proceed(self.model.stick)) + assert can_proceed(self.model.stick) self.model.stick() - self.assertEqual(self.model.state, "sticked") + assert self.model.state == "sticked" def test_field_available_transitions_works(self): self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" transitions = self.model.get_available_state_transitions() - self.assertEqual(["sticked"], [data.target for data in transitions]) + assert [data.target for data in transitions] == ["sticked"] def test_field_all_transitions_works(self): transitions = self.model.get_all_state_transitions() - self.assertEqual({("new", "published"), ("published", "sticked")}, {(data.source, data.target) for data in transitions}) + assert {("new", "published"), ("published", "sticked")} == {(data.source, data.target) for data in transitions} diff --git a/tests/testapp/tests/test_access_deferred_fsm_field.py b/tests/testapp/tests/test_access_deferred_fsm_field.py index bfcfa7b..e751cbb 100644 --- a/tests/testapp/tests/test_access_deferred_fsm_field.py +++ b/tests/testapp/tests/test_access_deferred_fsm_field.py @@ -29,9 +29,9 @@ def setUp(self): self.model = DeferrableModel.objects.only("id").get() def test_usecase(self): - self.assertEqual(self.model.state, "new") - self.assertTrue(can_proceed(self.model.remove)) + assert self.model.state == "new" + assert can_proceed(self.model.remove) self.model.remove() - self.assertEqual(self.model.state, "removed") - self.assertFalse(can_proceed(self.model.remove)) + assert self.model.state == "removed" + assert not can_proceed(self.model.remove) diff --git a/tests/testapp/tests/test_basic_transitions.py b/tests/testapp/tests/test_basic_transitions.py index 0414029..96deabf 100644 --- a/tests/testapp/tests/test_basic_transitions.py +++ b/tests/testapp/tests/test_basic_transitions.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -53,70 +54,74 @@ def setUp(self): self.model = SimpleBlogPost() def test_initial_state_instantiated(self): - self.assertEqual(self.model.state, "new") + assert self.model.state == "new" def test_known_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" - self.assertTrue(can_proceed(self.model.hide)) + assert can_proceed(self.model.hide) self.model.hide() - self.assertEqual(self.model.state, "hidden") + assert self.model.state == "hidden" def test_unknown_transition_fails(self): - self.assertFalse(can_proceed(self.model.hide)) - self.assertRaises(TransitionNotAllowed, self.model.hide) + assert not can_proceed(self.model.hide) + with pytest.raises(TransitionNotAllowed): + self.model.hide() def test_state_non_changed_after_fail(self): - self.assertTrue(can_proceed(self.model.remove)) - self.assertRaises(Exception, self.model.remove) - self.assertEqual(self.model.state, "new") + assert can_proceed(self.model.remove) + with pytest.raises(Exception, match="Upss"): + self.model.remove() + assert self.model.state == "new" def test_allowed_null_transition_should_succeed(self): self.model.publish() self.model.notify_all() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" def test_unknown_null_transition_should_fail(self): - self.assertRaises(TransitionNotAllowed, self.model.notify_all) - self.assertEqual(self.model.state, "new") + with pytest.raises(TransitionNotAllowed): + self.model.notify_all() + assert self.model.state == "new" def test_multiple_source_support_path_1_works(self): self.model.publish() self.model.steal() - self.assertEqual(self.model.state, "stolen") + assert self.model.state == "stolen" def test_multiple_source_support_path_2_works(self): self.model.publish() self.model.hide() self.model.steal() - self.assertEqual(self.model.state, "stolen") + assert self.model.state == "stolen" def test_star_shortcut_succeed(self): - self.assertTrue(can_proceed(self.model.moderate)) + assert can_proceed(self.model.moderate) self.model.moderate() - self.assertEqual(self.model.state, "moderated") + assert self.model.state == "moderated" def test_plus_shortcut_succeeds_for_other_source(self): """Tests that the '+' shortcut succeeds for a source other than the target. """ - self.assertTrue(can_proceed(self.model.block)) + assert can_proceed(self.model.block) self.model.block() - self.assertEqual(self.model.state, "blocked") + assert self.model.state == "blocked" def test_plus_shortcut_fails_for_same_source(self): """Tests that the '+' shortcut fails if the source equals the target. """ self.model.block() - self.assertFalse(can_proceed(self.model.block)) - self.assertRaises(TransitionNotAllowed, self.model.block) + assert not can_proceed(self.model.block) + with pytest.raises(TransitionNotAllowed): + self.model.block() def test_empty_string_target(self): self.model.empty() - self.assertEqual(self.model.state, "") + assert self.model.state == "" class StateSignalsTests(TestCase): @@ -128,22 +133,23 @@ def setUp(self): post_transition.connect(self.on_post_transition, sender=SimpleBlogPost) def on_pre_transition(self, sender, instance, name, source, target, **kwargs): - self.assertEqual(instance.state, source) + assert instance.state == source self.pre_transition_called = True def on_post_transition(self, sender, instance, name, source, target, **kwargs): - self.assertEqual(instance.state, target) + assert instance.state == target self.post_transition_called = True def test_signals_called_on_valid_transition(self): self.model.publish() - self.assertTrue(self.pre_transition_called) - self.assertTrue(self.post_transition_called) + assert self.pre_transition_called + assert self.post_transition_called def test_signals_not_called_on_invalid_transition(self): - self.assertRaises(TransitionNotAllowed, self.model.hide) - self.assertFalse(self.pre_transition_called) - self.assertFalse(self.post_transition_called) + with pytest.raises(TransitionNotAllowed): + self.model.hide() + assert not self.pre_transition_called + assert not self.post_transition_called class TestFieldTransitionsInspect(TestCase): @@ -154,8 +160,8 @@ def test_in_operator_for_available_transitions(self): # store the generator in a list, so we can reuse the generator and do multiple asserts transitions = list(self.model.get_available_state_transitions()) - self.assertIn("publish", transitions) - self.assertNotIn("xyz", transitions) + assert "publish" in transitions + assert "xyz" not in transitions # inline method for faking the name of the transition def publish(): @@ -171,13 +177,13 @@ def publish(): custom="", ) - self.assertTrue(obj in transitions) + assert obj in transitions def test_available_conditions_from_new(self): transitions = self.model.get_available_state_transitions() actual = {(transition.source, transition.target) for transition in transitions} expected = {("*", "moderated"), ("new", "published"), ("new", "removed"), ("*", ""), ("+", "blocked")} - self.assertEqual(actual, expected) + assert actual == expected def test_available_conditions_from_published(self): self.model.publish() @@ -191,7 +197,7 @@ def test_available_conditions_from_published(self): ("*", ""), ("+", "blocked"), } - self.assertEqual(actual, expected) + assert actual == expected def test_available_conditions_from_hidden(self): self.model.publish() @@ -199,7 +205,7 @@ def test_available_conditions_from_hidden(self): transitions = self.model.get_available_state_transitions() actual = {(transition.source, transition.target) for transition in transitions} expected = {("*", "moderated"), ("hidden", "stolen"), ("*", ""), ("+", "blocked")} - self.assertEqual(actual, expected) + assert actual == expected def test_available_conditions_from_stolen(self): self.model.publish() @@ -207,21 +213,21 @@ def test_available_conditions_from_stolen(self): transitions = self.model.get_available_state_transitions() actual = {(transition.source, transition.target) for transition in transitions} expected = {("*", "moderated"), ("*", ""), ("+", "blocked")} - self.assertEqual(actual, expected) + assert actual == expected def test_available_conditions_from_blocked(self): self.model.block() transitions = self.model.get_available_state_transitions() actual = {(transition.source, transition.target) for transition in transitions} expected = {("*", "moderated"), ("*", "")} - self.assertEqual(actual, expected) + assert actual == expected def test_available_conditions_from_empty(self): self.model.empty() transitions = self.model.get_available_state_transitions() actual = {(transition.source, transition.target) for transition in transitions} expected = {("*", "moderated"), ("*", ""), ("+", "blocked")} - self.assertEqual(actual, expected) + assert actual == expected def test_all_conditions(self): transitions = self.model.get_all_state_transitions() @@ -238,4 +244,4 @@ def test_all_conditions(self): ("*", ""), ("+", "blocked"), } - self.assertEqual(actual, expected) + assert actual == expected diff --git a/tests/testapp/tests/test_conditions.py b/tests/testapp/tests/test_conditions.py index 0682760..610b7ff 100644 --- a/tests/testapp/tests/test_conditions.py +++ b/tests/testapp/tests/test_conditions.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -36,17 +37,18 @@ def setUp(self): self.model = BlogPostWithConditions() def test_initial_staet(self): - self.assertEqual(self.model.state, "new") + assert self.model.state == "new" def test_known_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" def test_unmet_condition(self): self.model.publish() - self.assertEqual(self.model.state, "published") - self.assertFalse(can_proceed(self.model.destroy)) - self.assertRaises(TransitionNotAllowed, self.model.destroy) + assert self.model.state == "published" + assert not can_proceed(self.model.destroy) + with pytest.raises(TransitionNotAllowed): + self.model.destroy() - self.assertTrue(can_proceed(self.model.destroy, check_conditions=False)) + assert can_proceed(self.model.destroy, check_conditions=False) diff --git a/tests/testapp/tests/test_custom_data.py b/tests/testapp/tests/test_custom_data.py index 66e6232..aa0ac8b 100644 --- a/tests/testapp/tests/test_custom_data.py +++ b/tests/testapp/tests/test_custom_data.py @@ -31,14 +31,14 @@ def setUp(self): self.model = BlogPostWithCustomData() def test_initial_state(self): - self.assertEqual(self.model.state, "new") + assert self.model.state == "new" transitions = list(self.model.get_available_state_transitions()) - self.assertEqual(len(transitions), 1) - self.assertEqual(transitions[0].target, "published") - self.assertDictEqual(transitions[0].custom, {"label": "Publish", "type": "*"}) + assert len(transitions) == 1 + assert transitions[0].target == "published" + assert transitions[0].custom == {"label": "Publish", "type": "*"} def test_all_transitions_have_custom_data(self): transitions = self.model.get_all_state_transitions() for t in transitions: - self.assertIsNotNone(t.custom["label"]) - self.assertIsNotNone(t.custom["type"]) + assert t.custom["label"] is not None + assert t.custom["type"] is not None diff --git a/tests/testapp/tests/test_exception_transitions.py b/tests/testapp/tests/test_exception_transitions.py index 4ec54e4..080caf7 100644 --- a/tests/testapp/tests/test_exception_transitions.py +++ b/tests/testapp/tests/test_exception_transitions.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -34,14 +35,16 @@ def on_post_transition(self, **kwargs): self.post_transition_data = kwargs def test_state_changed_after_fail(self): - self.assertTrue(can_proceed(self.model.publish)) - self.assertRaises(Exception, self.model.publish) - self.assertEqual(self.model.state, "crashed") - self.assertEqual(self.post_transition_data["target"], "crashed") - self.assertTrue("exception" in self.post_transition_data) + assert can_proceed(self.model.publish) + with pytest.raises(Exception, match="Upss"): + self.model.publish() + assert self.model.state == "crashed" + assert self.post_transition_data["target"] == "crashed" + assert "exception" in self.post_transition_data def test_state_not_changed_after_fail(self): - self.assertTrue(can_proceed(self.model.delete)) - self.assertRaises(Exception, self.model.delete) - self.assertEqual(self.model.state, "new") - self.assertIsNone(self.post_transition_data) + assert can_proceed(self.model.delete) + with pytest.raises(Exception, match="Upss"): + self.model.delete() + assert self.model.state == "new" + assert self.post_transition_data is None diff --git a/tests/testapp/tests/test_integer_field.py b/tests/testapp/tests/test_integer_field.py index 31d03db..752a141 100644 --- a/tests/testapp/tests/test_integer_field.py +++ b/tests/testapp/tests/test_integer_field.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -32,10 +33,11 @@ def setUp(self): def test_known_transition_should_succeed(self): self.model.publish() - self.assertEqual(self.model.state, BlogPostStateEnum.PUBLISHED) + assert self.model.state == BlogPostStateEnum.PUBLISHED self.model.hide() - self.assertEqual(self.model.state, BlogPostStateEnum.HIDDEN) + assert self.model.state == BlogPostStateEnum.HIDDEN - def test_unknow_transition_fails(self): - self.assertRaises(TransitionNotAllowed, self.model.hide) + def test_unknown_transition_fails(self): + with pytest.raises(TransitionNotAllowed): + self.model.hide() diff --git a/tests/testapp/tests/test_key_field.py b/tests/testapp/tests/test_key_field.py index 5706c84..e9a9b95 100644 --- a/tests/testapp/tests/test_key_field.py +++ b/tests/testapp/tests/test_key_field.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -7,6 +8,7 @@ from django_fsm import TransitionNotAllowed from django_fsm import can_proceed from django_fsm import transition +from tests.testapp.models import DbState FK_AVAILABLE_STATES = ( ("New", "_NEW_"), @@ -18,23 +20,8 @@ ) -class DBState(models.Model): - id = models.CharField(primary_key=True, max_length=50) - - label = models.CharField(max_length=255) - - class Meta: - app_label = "django_fsm" - - def __str__(self): - return self.label - - class FKBlogPost(models.Model): - state = FSMKeyField(DBState, default="new", protected=True, on_delete=models.CASCADE) - - class Meta: - app_label = "django_fsm" + state = FSMKeyField(DbState, default="new", protected=True, on_delete=models.CASCADE) @transition(field=state, source="new", target="published") def publish(self): @@ -64,69 +51,66 @@ def moderate(self): class FSMKeyFieldTest(TestCase): def setUp(self): for item in FK_AVAILABLE_STATES: - DBState.objects.create(pk=item[0], label=item[1]) + DbState.objects.create(pk=item[0], label=item[1]) self.model = FKBlogPost() - def test_initial_state_instatiated(self): - self.assertEqual( - self.model.state, - "new", - ) + def test_initial_state_instantiated(self): + assert self.model.state == "new" def test_known_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" - self.assertTrue(can_proceed(self.model.hide)) + assert can_proceed(self.model.hide) self.model.hide() - self.assertEqual(self.model.state, "hidden") + assert self.model.state == "hidden" - def test_unknow_transition_fails(self): - self.assertFalse(can_proceed(self.model.hide)) - self.assertRaises(TransitionNotAllowed, self.model.hide) + def test_unknown_transition_fails(self): + assert not can_proceed(self.model.hide) + with pytest.raises(TransitionNotAllowed): + self.model.hide() def test_state_non_changed_after_fail(self): - self.assertTrue(can_proceed(self.model.remove)) - self.assertRaises(Exception, self.model.remove) - self.assertEqual(self.model.state, "new") + assert can_proceed(self.model.remove) + with pytest.raises(Exception, match="Upss"): + self.model.remove() + assert self.model.state == "new" def test_allowed_null_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() self.model.notify_all() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" - def test_unknow_null_transition_should_fail(self): - self.assertRaises(TransitionNotAllowed, self.model.notify_all) - self.assertEqual(self.model.state, "new") + def test_unknown_null_transition_should_fail(self): + with pytest.raises(TransitionNotAllowed): + self.model.notify_all() + assert self.model.state == "new" - def test_mutiple_source_support_path_1_works(self): + def test_multiple_source_support_path_1_works(self): self.model.publish() self.model.steal() - self.assertEqual(self.model.state, "stolen") + assert self.model.state == "stolen" - def test_mutiple_source_support_path_2_works(self): + def test_multiple_source_support_path_2_works(self): self.model.publish() self.model.hide() self.model.steal() - self.assertEqual(self.model.state, "stolen") + assert self.model.state == "stolen" def test_star_shortcut_succeed(self): - self.assertTrue(can_proceed(self.model.moderate)) + assert can_proceed(self.model.moderate) self.model.moderate() - self.assertEqual(self.model.state, "moderated") + assert self.model.state == "moderated" """ # TODO: FIX it class BlogPostStatus(models.Model): - name = models.CharField(max_length=10, unique=True) + name = models.CharField(unique=True, max_length=10) objects = models.Manager() - class Meta: - app_label = 'django_fsm' - class BlogPostWithFKState(models.Model): status = FSMKeyField(BlogPostStatus, default=lambda: BlogPostStatus.objects.get(name="new")) @@ -154,6 +138,7 @@ def test_known_transition_should_succeed(self): self.model.hide() self.assertEqual(self.model.state, 'hidden') - def test_unknow_transition_fails(self): - self.assertRaises(TransitionNotAllowed, self.model.hide) + def test_unknown_transition_fails(self): + with pytest.raises(TransitionNotAllowed): + self.model.hide() """ diff --git a/tests/testapp/tests/test_lock_mixin.py b/tests/testapp/tests/test_lock_mixin.py index 6eedcfb..9867934 100644 --- a/tests/testapp/tests/test_lock_mixin.py +++ b/tests/testapp/tests/test_lock_mixin.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -47,12 +48,12 @@ def test_crud_succeed(self): post.save() post = LockedBlogPost.objects.get(pk=post.pk) - self.assertEqual("published", post.state) + assert post.state == "published" post.text = "test_crud_succeed2" post.save() post = LockedBlogPost.objects.get(pk=post.pk) - self.assertEqual("test_crud_succeed2", post.text) + assert post.text == "test_crud_succeed2" post.delete() @@ -75,7 +76,7 @@ def test_concurrent_modifications_raise_exception(self): post2.text = "aaa" post2.publish() - with self.assertRaises(ConcurrentTransition): + with pytest.raises(ConcurrentTransition): post2.save() def test_inheritance_crud_succeed(self): @@ -84,14 +85,14 @@ def test_inheritance_crud_succeed(self): post.save() post = ExtendedBlogPost.objects.get(pk=post.pk) - self.assertEqual("published", post.state) + assert post.state == "published" post.text = "test_inheritance_crud_succeed2" post.reject() post.save() post = ExtendedBlogPost.objects.get(pk=post.pk) - self.assertEqual("rejected", post.review_state) - self.assertEqual("test_inheritance_crud_succeed2", post.text) + assert post.review_state == "rejected" + assert post.text == "test_inheritance_crud_succeed2" def test_concurrent_modifications_after_refresh_db_succeed(self): # bug 255 post1 = LockedBlogPost.objects.create() diff --git a/tests/testapp/tests/test_mixin_support.py b/tests/testapp/tests/test_mixin_support.py index 23e8be5..e75b05f 100644 --- a/tests/testapp/tests/test_mixin_support.py +++ b/tests/testapp/tests/test_mixin_support.py @@ -29,7 +29,7 @@ def test_usecase(self): model = MixinSupportTestModel() model.draft() - self.assertEqual(model.state, "draft") + assert model.state == "draft" model.publish() - self.assertEqual(model.state, "published") + assert model.state == "published" diff --git a/tests/testapp/tests/test_multi_resultstate.py b/tests/testapp/tests/test_multi_resultstate.py index 88c6cde..7451479 100644 --- a/tests/testapp/tests/test_multi_resultstate.py +++ b/tests/testapp/tests/test_multi_resultstate.py @@ -34,12 +34,12 @@ class Test(TestCase): def test_return_state_succeed(self): instance = MultiResultTest() instance.publish(is_public=True) - self.assertEqual(instance.state, "published") + assert instance.state == "published" def test_get_state_succeed(self): instance = MultiResultTest(state="for_moderators") instance.moderate(allowed=False) - self.assertEqual(instance.state, "rejected") + assert instance.state == "rejected" class TestSignals(TestCase): @@ -50,21 +50,21 @@ def setUp(self): post_transition.connect(self.on_post_transition, sender=MultiResultTest) def on_pre_transition(self, sender, instance, name, source, target, **kwargs): - self.assertEqual(instance.state, source) + assert instance.state == source self.pre_transition_called = True def on_post_transition(self, sender, instance, name, source, target, **kwargs): - self.assertEqual(instance.state, target) + assert instance.state == target self.post_transition_called = True def test_signals_called_with_get_state(self): instance = MultiResultTest(state="for_moderators") instance.moderate(allowed=False) - self.assertTrue(self.pre_transition_called) - self.assertTrue(self.post_transition_called) + assert self.pre_transition_called + assert self.post_transition_called def test_signals_called_with_return_value(self): instance = MultiResultTest() instance.publish(is_public=True) - self.assertTrue(self.pre_transition_called) - self.assertTrue(self.post_transition_called) + assert self.pre_transition_called + assert self.post_transition_called diff --git a/tests/testapp/tests/test_multidecorators.py b/tests/testapp/tests/test_multidecorators.py index e1c669d..6eda60c 100644 --- a/tests/testapp/tests/test_multidecorators.py +++ b/tests/testapp/tests/test_multidecorators.py @@ -34,5 +34,5 @@ class TestStateProxy(TestCase): def test_transition_method_called_once(self): model = TestModel() model.review() - self.assertEqual(1, model.counter) - self.assertEqual(1, model.signal_counter) + assert model.counter == 1 + assert model.signal_counter == 1 diff --git a/tests/testapp/tests/test_object_permissions.py b/tests/testapp/tests/test_object_permissions.py index 29bf2e7..47e63b3 100644 --- a/tests/testapp/tests/test_object_permissions.py +++ b/tests/testapp/tests/test_object_permissions.py @@ -40,13 +40,13 @@ def setUp(self): super().setUp() self.model = ObjectPermissionTestModel.objects.create() - self.unprivileged = User.objects.create(username="unpriviledged") + self.unprivileged = User.objects.create(username="unprivileged") self.privileged = User.objects.create(username="object_only_privileged") assign_perm("can_publish_objectpermissiontestmodel", self.privileged, self.model) def test_object_only_access_success(self): - self.assertTrue(has_transition_perm(self.model.publish, self.privileged)) + assert has_transition_perm(self.model.publish, self.privileged) self.model.publish() def test_object_only_other_access_prohibited(self): - self.assertFalse(has_transition_perm(self.model.publish, self.unprivileged)) + assert not has_transition_perm(self.model.publish, self.unprivileged) diff --git a/tests/testapp/tests/test_permissions.py b/tests/testapp/tests/test_permissions.py index 67b4561..a343e68 100644 --- a/tests/testapp/tests/test_permissions.py +++ b/tests/testapp/tests/test_permissions.py @@ -11,27 +11,27 @@ class PermissionFSMFieldTest(TestCase): def setUp(self): self.model = BlogPost() - self.unpriviledged = User.objects.create(username="unpriviledged") - self.priviledged = User.objects.create(username="priviledged") + self.unprivileged = User.objects.create(username="unprivileged") + self.privileged = User.objects.create(username="privileged") self.staff = User.objects.create(username="staff", is_staff=True) - self.priviledged.user_permissions.add(Permission.objects.get_by_natural_key("can_publish_post", "testapp", "blogpost")) - self.priviledged.user_permissions.add(Permission.objects.get_by_natural_key("can_remove_post", "testapp", "blogpost")) + self.privileged.user_permissions.add(Permission.objects.get_by_natural_key("can_publish_post", "testapp", "blogpost")) + self.privileged.user_permissions.add(Permission.objects.get_by_natural_key("can_remove_post", "testapp", "blogpost")) - def test_proviledged_access_succed(self): - self.assertTrue(has_transition_perm(self.model.publish, self.priviledged)) - self.assertTrue(has_transition_perm(self.model.remove, self.priviledged)) + def test_proviledged_access_succeed(self): + assert has_transition_perm(self.model.publish, self.privileged) + assert has_transition_perm(self.model.remove, self.privileged) - transitions = self.model.get_available_user_state_transitions(self.priviledged) - self.assertEqual({"publish", "remove", "moderate"}, {transition.name for transition in transitions}) + transitions = self.model.get_available_user_state_transitions(self.privileged) + assert {"publish", "remove", "moderate"} == {transition.name for transition in transitions} - def test_unpriviledged_access_prohibited(self): - self.assertFalse(has_transition_perm(self.model.publish, self.unpriviledged)) - self.assertFalse(has_transition_perm(self.model.remove, self.unpriviledged)) + def test_unprivileged_access_prohibited(self): + assert not has_transition_perm(self.model.publish, self.unprivileged) + assert not has_transition_perm(self.model.remove, self.unprivileged) - transitions = self.model.get_available_user_state_transitions(self.unpriviledged) - self.assertEqual({"moderate"}, {transition.name for transition in transitions}) + transitions = self.model.get_available_user_state_transitions(self.unprivileged) + assert {"moderate"} == {transition.name for transition in transitions} def test_permission_instance_method(self): - self.assertFalse(has_transition_perm(self.model.restore, self.unpriviledged)) - self.assertTrue(has_transition_perm(self.model.restore, self.staff)) + assert not has_transition_perm(self.model.restore, self.unprivileged) + assert has_transition_perm(self.model.restore, self.staff) diff --git a/tests/testapp/tests/test_protected_field.py b/tests/testapp/tests/test_protected_field.py index 0ef8684..f595818 100644 --- a/tests/testapp/tests/test_protected_field.py +++ b/tests/testapp/tests/test_protected_field.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -10,9 +11,6 @@ class ProtectedAccessModel(models.Model): status = FSMField(default="new", protected=True) - class Meta: - app_label = "django_fsm" - @transition(field=status, source="new", target="published") def publish(self): pass @@ -22,25 +20,23 @@ class MultiProtectedAccessModel(models.Model): status1 = FSMField(default="new", protected=True) status2 = FSMField(default="new", protected=True) - class Meta: - app_label = "django_fsm" - class TestDirectAccessModels(TestCase): def test_multi_protected_field_create(self): obj = MultiProtectedAccessModel.objects.create() - self.assertEqual(obj.status1, "new") - self.assertEqual(obj.status2, "new") + assert obj.status1 == "new" + assert obj.status2 == "new" def test_no_direct_access(self): instance = ProtectedAccessModel() - self.assertEqual(instance.status, "new") + assert instance.status == "new" def try_change(): instance.status = "change" - self.assertRaises(AttributeError, try_change) + with pytest.raises(AttributeError): + try_change() instance.publish() instance.save() - self.assertEqual(instance.status, "published") + assert instance.status == "published" diff --git a/tests/testapp/tests/test_protected_fields.py b/tests/testapp/tests/test_protected_fields.py index c905c5c..ce98f88 100644 --- a/tests/testapp/tests/test_protected_fields.py +++ b/tests/testapp/tests/test_protected_fields.py @@ -1,5 +1,6 @@ from __future__ import annotations +import pytest from django.db import models from django.test import TestCase @@ -11,9 +12,6 @@ class RefreshableProtectedAccessModel(models.Model): status = FSMField(default="new", protected=True) - class Meta: - app_label = "django_fsm" - @transition(field=status, source="new", target="published") def publish(self): pass @@ -26,16 +24,17 @@ class RefreshableModel(FSMModelMixin, RefreshableProtectedAccessModel): class TestDirectAccessModels(TestCase): def test_no_direct_access(self): instance = RefreshableProtectedAccessModel() - self.assertEqual(instance.status, "new") + assert instance.status == "new" def try_change(): instance.status = "change" - self.assertRaises(AttributeError, try_change) + with pytest.raises(AttributeError): + try_change() instance.publish() instance.save() - self.assertEqual(instance.status, "published") + assert instance.status == "published" def test_refresh_from_db(self): instance = RefreshableModel() diff --git a/tests/testapp/tests/test_proxy_inheritance.py b/tests/testapp/tests/test_proxy_inheritance.py index cef7d13..7cb73b6 100644 --- a/tests/testapp/tests/test_proxy_inheritance.py +++ b/tests/testapp/tests/test_proxy_inheritance.py @@ -30,24 +30,24 @@ def setUp(self): self.model = InheritedModel() def test_known_transition_should_succeed(self): - self.assertTrue(can_proceed(self.model.publish)) + assert can_proceed(self.model.publish) self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" - self.assertTrue(can_proceed(self.model.stick)) + assert can_proceed(self.model.stick) self.model.stick() - self.assertEqual(self.model.state, "sticked") + assert self.model.state == "sticked" def test_field_available_transitions_works(self): self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" transitions = self.model.get_available_state_transitions() - self.assertEqual(["sticked"], [data.target for data in transitions]) + assert [data.target for data in transitions] == ["sticked"] def test_field_all_transitions_base_model(self): transitions = BaseModel().get_all_state_transitions() - self.assertEqual({("new", "published")}, {(data.source, data.target) for data in transitions}) + assert {("new", "published")} == {(data.source, data.target) for data in transitions} def test_field_all_transitions_works(self): transitions = self.model.get_all_state_transitions() - self.assertEqual({("new", "published"), ("published", "sticked")}, {(data.source, data.target) for data in transitions}) + assert {("new", "published"), ("published", "sticked")} == {(data.source, data.target) for data in transitions} diff --git a/tests/testapp/tests/test_state_transitions.py b/tests/testapp/tests/test_state_transitions.py index dd39e2d..23dfe38 100644 --- a/tests/testapp/tests/test_state_transitions.py +++ b/tests/testapp/tests/test_state_transitions.py @@ -55,16 +55,16 @@ def fly(self): class TestStateProxy(TestCase): def test_initial_proxy_set_succeed(self): insect = Insect() - self.assertTrue(isinstance(insect, Caterpillar)) + assert isinstance(insect, Caterpillar) def test_transition_proxy_set_succeed(self): insect = Insect() insect.cocoon() - self.assertTrue(isinstance(insect, Butterfly)) + assert isinstance(insect, Butterfly) def test_load_proxy_set(self): Insect.objects.create(state=Insect.STATE.CATERPILLAR) Insect.objects.create(state=Insect.STATE.BUTTERFLY) insects = Insect.objects.all() - self.assertEqual({Caterpillar, Butterfly}, {insect.__class__ for insect in insects}) + assert {Caterpillar, Butterfly} == {insect.__class__ for insect in insects} diff --git a/tests/testapp/tests/test_string_field_parameter.py b/tests/testapp/tests/test_string_field_parameter.py index 38e9102..34ed80d 100644 --- a/tests/testapp/tests/test_string_field_parameter.py +++ b/tests/testapp/tests/test_string_field_parameter.py @@ -31,6 +31,6 @@ def setUp(self): self.model = BlogPostWithStringField() def test_initial_state(self): - self.assertEqual(self.model.state, "new") + assert self.model.state == "new" self.model.publish() - self.assertEqual(self.model.state, "published") + assert self.model.state == "published" diff --git a/tests/testapp/tests/test_transition_all_except_target.py b/tests/testapp/tests/test_transition_all_except_target.py index f5d1b7e..fda48aa 100644 --- a/tests/testapp/tests/test_transition_all_except_target.py +++ b/tests/testapp/tests/test_transition_all_except_target.py @@ -28,9 +28,9 @@ def setUp(self): self.model = TestExceptTargetTransitionShortcut() def test_usecase(self): - self.assertEqual(self.model.state, "new") - self.assertTrue(can_proceed(self.model.remove)) + assert self.model.state == "new" + assert can_proceed(self.model.remove) self.model.remove() - self.assertEqual(self.model.state, "removed") - self.assertFalse(can_proceed(self.model.remove)) + assert self.model.state == "removed" + assert not can_proceed(self.model.remove)