当前位置:网站首页>Pytest unit test series [v1.0.0] [pytest execute unittest test case]

Pytest unit test series [v1.0.0] [pytest execute unittest test case]

2022-07-06 22:52:00 Davieyang

Pytest perform unittest Use cases

unittest Is built on python Unit test framework of standard library , Originally used for testing python Their own , Later, it is also commonly used in unit testing and automated testing of various projects or products , and pytest Can be like unittest Same operation , And can run simultaneously in the same session pytest Use cases and unittest Use cases .
Still Task Project as the tested content , The following code is unittest Use cases under the framework

import unittest
import shutil
import tempfile
import tasks
from tasks import Task


def setUpModule():
    """Make temp dir, initialize DB."""
    global temp_dir
    temp_dir = tempfile.mkdtemp()
    tasks.start_tasks_db(str(temp_dir), 'tiny')


def tearDownModule():
    """Clean up DB, remove temp dir."""
    tasks.stop_tasks_db()
    shutil.rmtree(temp_dir)


class TestNonEmpty(unittest.TestCase):

    def setUp(self):
        tasks.delete_all()  # start empty
        # add a few items, saving ids
        self.ids = []
        self.ids.append(tasks.add(Task('One', 'Brian', True)))
        self.ids.append(tasks.add(Task('Two', 'Still Brian', False)))
        self.ids.append(tasks.add(Task('Three', 'Not Brian', False)))

    def test_delete_decreases_count(self):
        # GIVEN 3 items
        self.assertEqual(tasks.count(), 3)
        # WHEN we delete one
        tasks.delete(self.ids[0])
        # THEN count decreases by 1
        self.assertEqual(tasks.count(), 2)

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

use pytest Carry out this paragraph unittest Use cases under the framework :

[email protected]-Pro unittest$pytest -v test_delete_unittest.py 
======================= test session starts ============================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/SourceCode/ch7/unittest
collected 1 item                                                                                                                                                                

test_delete_unittest.py::TestNonEmpty::test_delete_decreases_count PASSED                                                                                                 [100%]

========================= 1 passed in 0.08s ==========================

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

Use unittest Execute this use case :

[email protected]-Pro unittest$python3 -m unittest  -v test_delete_unittest.py 
test_delete_decreases_count (test_delete_unittest.TestNonEmpty) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.019s

OK

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

One more pytest Use cases , As shown in the following code :

import tasks


def test_delete_decreases_count(db_with_3_tasks):
    ids = [t.id for t in tasks.list_tasks()]
    # GIVEN 3 items
    assert tasks.count() == 3
    # WHEN we delete one
    tasks.delete(ids[0])
    # THEN count decreases by 1
    assert tasks.count() == 2

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

use pytest Execute two py file :

[email protected]-Pro unittest$pytest -v test_delete_unittest.py test_delete_pytest.py 
================ test session starts =======================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/SourceCode/ch7/unittest
collected 2 items                                                                                                                                                            

test_delete_unittest.py::TestNonEmpty::test_delete_decreases_count PASSED                                                                                              [ 50%]
test_delete_pytest.py::test_delete_decreases_count PASSED                                                                                                              [100%]

==================== 2 passed in 0.08s ====================

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

Run two separately py file :

[email protected]-Pro unittest$pytest -q test_delete_pytest.py 
.                                                                                                                                                                      [100%]
1 passed in 0.02s

      
  • 1.
  • 2.
  • 3.
[email protected]-Pro unittest$pytest -q test_delete_unittest.py 
.                                                                                                                                                                      [100%]
1 passed in 0.02s

      
  • 1.
  • 2.
  • 3.

The above implementation methods can be carried out smoothly , When we execute at the same time pytest Use cases and unittest Use case , If pytest before , The results are as follows , Just change the order of the two files

[email protected]-Pro unittest$pytest -v test_delete_pytest.py test_delete_unittest.py
================= test session starts ===================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/SourceCode/ch7/unittest
collected 2 items                                                                                                                                                            

test_delete_pytest.py::test_delete_decreases_count PASSED                                                                                                              [ 50%]
test_delete_unittest.py::TestNonEmpty::test_delete_decreases_count PASSED                                                                                              [100%]
test_delete_unittest.py::TestNonEmpty::test_delete_decreases_count ERROR                                                                                               [100%]

================== ERRORS =========================
_______________________________________________________ ERROR at teardown of TestNonEmpty.test_delete_decreases_count ________________________________________________________

tmpdir_factory = TempdirFactory(_tmppath_factory=TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x10516de48>, _basetemp=PosixPath('/private/var/folders/8z/8hpwg8c9719b667kqs0qrqrw0000gn/T/pytest-of-DY/pytest-2')))
request = <SubRequest 'tasks_db_session' for <Function test_delete_decreases_count>>

    @pytest.fixture(scope='session')
    def tasks_db_session(tmpdir_factory, request):
        """Connect to db before tests, disconnect after."""
        temp_dir = tmpdir_factory.mktemp('temp')
        tasks.start_tasks_db(str(temp_dir), 'tiny')
        yield  # this is where the testing happens
>       tasks.stop_tasks_db()

conftest.py:12: 
_ _ _  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def stop_tasks_db():  # type: () -> None
        """Disconnect API functions from db."""
        global _tasksdb
>       _tasksdb.stop_tasks_db()
E       AttributeError: 'NoneType' object has no attribute 'stop_tasks_db'

/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/tasks/api.py:129: AttributeError
================ 2 passed, 1 error in 0.10s ================

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.

use –setup-show Further study

[email protected]-Pro unittest$pytest -q --setup-show --tb=no test_delete_pytest.py test_delete_unittest.py

SETUP    S tmpdir_factory
SETUP    S tasks_db_session (fixtures used: tmpdir_factory)
        SETUP    F tasks_db (fixtures used: tasks_db_session)
        SETUP    F tasks_just_a_few
        SETUP    F db_with_3_tasks (fixtures used: tasks_db, tasks_just_a_few)
        test_delete_pytest.py::test_delete_decreases_count (fixtures used: db_with_3_tasks, tasks_db, tasks_db_session, tasks_just_a_few, tmpdir_factory).
        TEARDOWN F db_with_3_tasks
        TEARDOWN F tasks_just_a_few
        TEARDOWN F tasks_db
    SETUP    M _Module__pytest_setup_module
      SETUP    C _UnitTestCase__pytest_class_setup
        test_delete_unittest.py::TestNonEmpty::test_delete_decreases_count (fixtures used: _Module__pytest_setup_module, _UnitTestCase__pytest_class_setup).
      TEARDOWN C _UnitTestCase__pytest_class_setup
    TEARDOWN M _Module__pytest_setup_module
TEARDOWN S tasks_db_session
TEARDOWN S tmpdir_factoryE
2 passed, 1 error in 0.11s


      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

Session wide teardown fixtures It will be executed after all tests , These include unittest The use case , and unittest Inside tearDownModule() The database link has been closed ,pytest Inside tasks_db_sessions() teardown If you do the same thing again, you will fail .
Fix this problem , Can be in unittest Use in pytest Of fixture, As shown in the following code :

import pytest
import unittest
import tasks
from tasks import Task


@pytest.mark.usefixtures('tasks_db_session')
class TestNonEmpty(unittest.TestCase):

    def setUp(self):
        tasks.delete_all()  # start empty
        # add a few items, saving ids
        self.ids = []
        self.ids.append(tasks.add(Task('One', 'Brian', True)))
        self.ids.append(tasks.add(Task('Two', 'Still Brian', False)))
        self.ids.append(tasks.add(Task('Three', 'Not Brian', False)))

    def test_delete_decreases_count(self):
        # GIVEN 3 items
        self.assertEqual(tasks.count(), 3)
        # WHEN we delete one
        tasks.delete(self.ids[0])
        # THEN count decreases by 1
        self.assertEqual(tasks.count(), 2)

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

Execute use case again :

[email protected]-Pro unittest$pytest -q --setup-show --tb=no test_delete_pytest.py test_delete_unittest.py

SETUP    S tmpdir_factory
SETUP    S tasks_db_session (fixtures used: tmpdir_factory)
        SETUP    F tasks_db (fixtures used: tasks_db_session)
        SETUP    F tasks_just_a_few
        SETUP    F db_with_3_tasks (fixtures used: tasks_db, tasks_just_a_few)
        test_delete_pytest.py::test_delete_decreases_count (fixtures used: db_with_3_tasks, tasks_db, tasks_db_session, tasks_just_a_few, tmpdir_factory).
        TEARDOWN F db_with_3_tasks
        TEARDOWN F tasks_just_a_few
        TEARDOWN F tasks_db
      SETUP    C _UnitTestCase__pytest_class_setup
        test_delete_unittest_fix.py::TestNonEmpty::test_delete_decreases_count (fixtures used: _UnitTestCase__pytest_class_setup, tasks_db_session, tmpdir_factory).
      TEARDOWN C _UnitTestCase__pytest_class_setup
TEARDOWN S tasks_db_session
TEARDOWN S tmpdir_factory
2 passed in 0.06s

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

Here we only need to talk inside pytest and unittest Share resources between , At the same time, you can also pytest markers Use in unittest On , for example @pytest.mark.skip()/@pytest.mark.xfail(), Or customized
However, there is a small problem , stay unittest On the use of pytest.mark.usefixtures, It's not from fixture Pass data directly to unittest function , To achieve this transfer , Can use cls object , As shown in the following code

import pytest
import unittest
import tasks
from tasks import Task


@pytest.fixture()
def tasks_db_non_empty(tasks_db_session, request):
    tasks.delete_all()  # start empty
    # add a few items, saving ids
    ids = []
    ids.append(tasks.add(Task('One', 'Brian', True)))
    ids.append(tasks.add(Task('Two', 'Still Brian', False)))
    ids.append(tasks.add(Task('Three', 'Not Brian', False)))
    request.cls.ids = ids


@pytest.mark.usefixtures('tasks_db_non_empty')
class TestNonEmpty(unittest.TestCase):

    def test_delete_decreases_count(self):
        # GIVEN 3 items
        self.assertEqual(tasks.count(), 3)
        # WHEN we delete one
        tasks.delete(self.ids[0])
        # THEN count decreases by 1
        self.assertEqual(tasks.count(), 2)

      
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

There is a limitation to using tags : be based on unittest Test cases of cannot be used parametrized Of fixture, The last example uses both pytest fixture and unittest, Reconstitute it pytest The format of test cases is not difficult , Just remove it unittest.TestCase Base class and modify assert You can use it in the same way
Another limitation ,unittest The test subset of stops executing when it first encounters an error , But when used alone unittest when , Whether there is any mistake ,unittest Will run each test subset in turn . Unless all test subsets can pass , otherwise pytest Not all

原网站

版权声明
本文为[Davieyang]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202131045250434.html