Pytest - One Solution for Unit, Functional and Acceptance Tests
Python: A tester’s choice
Python is a general purpose, dynamic and flexible language, hence a lot of applications are being developed using Python. From a tester’s perspective, it has readily available modules and libraries which make scripts creation a lot easier. Tests can be written as xUnit-style classes or as functions. It provides full fledge automation testing solution for any sort of project cause and It is capable enough to perform unit, functional, system and BDD testing. Pytest: Best among all python testing frameworks Pytest is a python testing framework which provides a single solution for unit, functional and Acceptance testing. It is popular than the other available frameworks because of its attractive features. Below are some of the features of Pytest:
- It offers test design with no boilerplate
- It does not require separate methods for assertion like assertEquals, assertTrue, assertContains
- Tests can be parametrized which reduces code duplication
- Pytest can run tests written in unittest, doctest, autres and nose
- 150+ external plugins available to support all sorts of functional testing
- Plugins available like pytest-BDD and pytest-konira for writing tests for Behaviour Driven Testing
- It works wonder for GUI automation testing, when used along with testing tools like selenium webdriver or splinter
In short pytest is a one stop solution for all sort of python testing be it unit, functional, highly complex functional or acceptance tests (BDD). Top Most Pytest Features and properties Pytest Fixtures: Nervous system of pytest Fixtures are the key concept in pytest which can essentially provide baseline for test creation and execution. To declare any method as fixture just put the annotation for the method “@pytest.fixture” and put them in “Conftest.py” Fixture example: @pytest.fixture def open_browser(): driver = webdriver.Firefox() driver.get("http://www.python.org") assert "Python" in driver.title The above designed fixture will be available for the whole project provided this should specified in project directory conftest.py file.
- Conftest.py file contains all configuration settings, all defined fixtures, hooks implementations and it is applicable to the directory level. They get loaded by default whenever tool is invoked.
Some key points on fixtures:
- Fixtures have names and can be called from anywhere in the project, modules, classes and tests
- Fixtures can return or not return any value or just execute the specified steps in it.
- Fixtures can be passed as function arguments and in that case the returning value of fixture will be available in the mentioned method.
- Fixture can be specified in directory level conftest.py file. Can be called from any method and it will execute the steps specified in it.
- A fixture can take multiple fixtures, and each fixture triggers other fixture, thus serves a modular approach.
- Fixtures can be scoped as per the need. This is a good practice keeping in mind time-expensiveness. Scope can be “session”, “module”, “class” and “function”.
Request object: Introspect agent This is one of the useful features to search or introspect the “requesting item”. It can introspect from test function, class, module, or session. Items specified in config file or returning by some other fixtures can be used efficiently by the called fixture by “getattr” function. Just check the below mentioned fixture:
@pytest.fixture def driver(request, browser_type): """return a webdriver instance for testing try: _driver = getattr(webdriver, browser_type)() except AttributeError as error: logger.info("Browser type %s unavailable!", browser_type) raise AttributeError return _driver Finalization code: Setting up of teardown Fixture can be used for teardown as well. This can be achieved by using “yield” keyword. Just put the fixture with the annotation “@pytest.yield_fixture“ and put the steps after “yield” keyword in the fixture. And whenever fixture will go out of scope the steps after the “yield” keyword will serves as teardown process. Have a look at the below modified steps of the “driver” fixture.
@pytest.yield_fixture def driver(request, browser_type): """return a webdriver instance for testing try: _driver = getattr(webdriver, browser_type)() except AttributeError as error: logger.info("Browser type %s unavailable!", browser_type) raise AttributeError yield _driver logger.info('Finishing test”) logger.info('*************************') _driver.quit() In the above mentioned fixture whenever “browser_type” is not available the driver instance will be quit. Fixture parametrization: Enhances reusability Fixtures can be parametrized and can be executed multiple times with different set of data, the same way as a normal function is executed. Usefixtures: Call for fixture from anywhere One way by which fixtures can be made available anywhere in the project is by calling them by using the decorator “@pytest.mark.usefixtures("fixture_1", "fixture_2")”. Autouse fixture: Mark the fixture for all AF are the fixtures methods which get invoked without “usefixtures” decorator or “funcgars”. Any fixture can be registered for autouse. Just need to put keyword autouse with “True” flag. “pytest.fixture(scope="module",autouse=True)”. Fixture will run for a class or test or module as mentioned in the scope. If they are defined in conftest then they will be invoked by the all tests present below the directory. These fixtures are particularly useful to set applicable global settings for the test session. Auto Test Discovery in Pytest: Ease of execution One of the very useful features is auto test discovery in pytest. Its means it detects all the tests once execution command is invoked, user only need to specify the test modules and test with a prefix “test_*.” while designing . Command line arguments can be specified with tests names, directories, node ids and file names. In case of absence of any command line arguments then collection with start from specified ‘testpaths’ (provided they need to be configured). This feature help in running all the tests, multiple tests in groups, single test, and tests belong to specific directories. Alternatively test can be organized in specific folder structure as per the modules and thus can be executed as per the need.