Skillversitas

Running unittest Tests

The pytest collects the unittest.TestCase classes (the Test* the standard library's), so the legacy unittest suite runs under the pytest command without the python -m unittest - the setUp/tearDown map to the setup/teardown, the self.assertEqual and friends work (the no rewriting, the unittest's own message), and the addCleanup the finalizer. The unittest-specific asserts (assertRaises, the assertAlmostEqual) are available on the self, and the pytest fixtures can be injected into the TestCase method (the parameter name, the unittest 3.12+ the subTest the loop). This chapter covers the TestCase collection (the setUp/tearDown the mapping), the self.assert* (the no rewrite, the message), and the fixture injection into the TestCase (the parameter, the subTest).

The TestCase Collection

# the unittest.TestCase: the the pytest COLLECTS it
# (the the Test* the method,
#   the setUp/tearDown the setup)
import unittest
from texttools import word_count

class TestWordCount(unittest.TestCase):
    def setUp(self):
        self.text = "the quick brown fox"

    def test_count(self):
        self.assertEqual(word_count(self.text), 4)

    def test_empty(self):
        self.assertEqual(word_count(""), 0)

    def tearDown(self):
        self.text = None   # the cleanup
# the the COLLECTION: the the TestWordCount::test_count,
#   TestWordCount::test_empty (the
#   the)
# the the SETUP: the the setUp BEFORE each test (the
#   the fresh, the)

The pytest collects the unittest.TestCase by the Test* name and the test_* method (the TestWordCount::test_count the item), and the setUp/tearDown run around each test (the fresh instance, the setUp before, the tearDown after - the same lifecycle the unittest gives). The self.assert* methods work as the unittest wrote them (the assertEqual, the assertIn, the assertRaises context) - the no assertion rewriting (the unittest's own message, the no where line), and the addCleanup is the finalizer (the self.addCleanup(self.close) the after). The migration is the gradual: the legacy unittest suite runs under the pytest (the one command, the one report), and the new tests use the bare assert plus the fixture (the rewrite, the no boilerplate) - the two coexist, and the next section's fixture injection is the bridge the TestCase reaches the pytest fixture.

The self.assert* and the subTest

# the self.assert*: the the unittest's OWN message
# (the no
#   the rewrite, the)
import unittest
from texttools import word_count

class TestAsserts(unittest.TestCase):
    def test_assertEquals(self):
        self.assertEqual(word_count("a b"), 2,
                         "the count the the")
        # the msg the optional
        #   (the)

    def test_assertRaises(self):
        with self.assertRaises(ValueError):
            ...   # the

    def test_subTest(self):
        # the subTest: the LOOP the
        #   per-case (the
        #   the)
        for text, expected in [("", 0), ("a", 1)]:
            with self.subTest(text=text):
                self.assertEqual(word_count(text),
                                 expected)
# the the subTest: the
#   per-case IDENTIFIER (the failure
#   the [text=''] the case)

The self.assert* is the unittest's own assertion (the assertEqual the msg the optional, the assertRaises the context, the assertAlmostEqual the float) - the message is the unittest's (the 2 != 1, the no where line the rewrite does not reach the method call), and the subTest is the loop's per-case (the with self.subTest(text=text) the identifier, the failure the [text=''] the case, the rest continues - the subTest is the unittest's answer to the loop-in-test, the parametrize the pytest's). The fixture injection is the bridge: the TestCase method can request the pytest fixture by the parameter name (the def test_x(self, fixture_name), the unittest 3.12+ the subTest the loop) - the conftest fixture reaches the TestCase, and the migration is the fixture-first (the new setup the fixture, the legacy the setUp). The rule is the one: the legacy unittest runs under the pytest (the one command), the new tests use the bare assert plus the fixture (the rewrite), and the subTest is the loop's per-case the unittest keeps - the next chapter's mock is the dependency stub the both styles use.

The Working Rules

  • The TestCase is collected, the setUp/tearDown the mapping. The TestWordCount::test_count the item, the fresh instance per test, the addCleanup the finalizer - the legacy suite runs under the pytest command, the one report.
  • The self.assert* is the unittest's message, the no rewrite. The assertEqual the msg, the assertRaises the context, the assertAlmostEqual the float - the method call the rewriter does not reach, the message the unittest's own.
  • The subTest is the loop's per-case. The with self.subTest(text=text) the identifier, the failure the [text=''] the case, the rest continues - the unittest's answer to the loop-in-test, the parametrize the pytest's equivalent.
  • The fixture injection is the bridge. The TestCase method requests the pytest fixture by the parameter name (the 3.12+), the conftest reaches the TestCase - the migration is the fixture-first (the new setup the fixture, the legacy the setUp).

Summary

The pytest collects the unittest.TestCase by the Test* name and the test_* method (the TestWordCount::test_count the item), and the setUp/tearDown run around each test (the fresh instance, the addCleanup the finalizer) - the legacy suite runs under the pytest command without the python -m unittest. The self.assert* methods work as the unittest wrote them (the assertEqual the msg, the assertRaises the context) with the unittest's own message (the no assertion rewrite on the method call), and the subTest is the loop's per-case (the [text=''] the identifier, the rest continues). The fixture injection (the TestCase method requests the pytest fixture by the parameter name, the 3.12+) is the bridge, and the migration is the gradual: the legacy unittest under the pytest, the new tests the bare assert plus the fixture. The next chapter's unittest.mock is the dependency stub both styles use - the patch, the return_value, and the assert_called the mock's assertion.