Super detailed from entry to proficiency, pytest automated testing framework actual combat - fixtures and various ways to play (9)


foreword

When writing test cases, it will involve the preparation of the environment before the execution of the test cases and the cleaning of the environment after the execution of the test cases.

The code version of the test cases is no exception.

pytest automated testing framework: https://www.bilibili.com/video/BV18K411m7FH/

In the automated testing framework, we also need to write:
environment preparation code before use case execution (pre-work code)
environment cleanup work after use case execution (post-work code)

Usually, in automated testing frameworks, they are called fixtures.

As a test framework of python language, pytest has two implementation methods for its fixture.

One is xunit-style, which is very similar to the mechanism of the unittest framework, namely the setup/teardown series;
the other is its own fixture mechanism, declared with the @pytest.fixture decorator.

pytest fixture implementation method 1: xunit-style

The xunit-style of pytest has three levels of fixtures: test modules, test classes, and test functions.

1. Test function/method level: the pre- and post-execution of each test function.
Test method inside the test class:
pre-function name: setup_method
post-function name:
test function under the teardown_method module:
pre-function name: setup_function
post-function name: teardown_function

2. Test class level: a test class only executes pre- and post-position once.
Pre-function name: setup_class
Post-function name: teardown_class
Note: Decorate with @classmethod

3. Test module level: a test module only executes pre- and post-position once.
Pre-function name: setup_module
Post-function name: teardown_module

from selenium import webdriver
from time import sleep
from random import randint


def setup_module():
    print("====  模块级的 setup 操作  ====")


def teardown_module():
    print("====  模块级的 teardown 操作  ====")


def test_random():
    assert randint(1, 5) == 3


class TestWeb:

    @classmethod
    def setup_class(cls):
        print("====  测试类级的 setup 操作  ====")

    @classmethod
    def teardown_class(cls):
        print("====  测试类级的 teardown 操作  ====")

    def setup_method(self):
        print("====  测试用例级的 setup 操作  ====")
        self.driver = webdriver.Chrome()

    def teardown_method(self):
        print("====  测试用例级的 teardown 操作  ====")
        self.driver.quit()

    def test_search(self):
        self.driver.get("https://www.baidu.com/")
        self.driver.find_element_by_id("kw").send_keys("xxxxxx")
        self.driver.find_element_by_id("su").click()
        sleep(1)

pytest also supports running unittest test cases. The following features of unittest are supported:

@unittest.skip
setUp/tearDown;
setUpClass/tearDownClass;
setUpModule/tearDownModule;

pytest's fixture implementation method 2: fixture mechanism

Fixtures are defined via the @pytest.fixture decorator. A function is decorated with @pytest.fixture, then this function is a fixture.

When using fixture, it is divided into two parts: fixture definition and fixture call.

In addition, there are fixture sharing mechanisms and nested calling mechanisms.

1. Define fixture.
Fixture is realized by function;
use @pytest.fixture for decoration;

import pytest

@pytest.fixture
def init():
    pass

Both the pre-preparation code and the post-cleanup code are written in one function.

The pre-code and post-code are distinguished by the yeild keyword. The code before yeild is the pre-code, and the code after yeild is the post-code

In actual application scenarios, there may be only pre-preparation codes, or only post-clearance codes.

import pytest


@pytest.fixture
def init():
    print("用例执行之前,执行的代码")  # 前置代码 
    yield 
    print("用例执行之后,执行的代码")  # 后置代码
 

@pytest.fixture
def init2():
    print("用例执行之前,执行的代码")  # 只有用例执行之前的前置准备代码
  

@pytest.fixture
def init3():
    yield
    print("用例执行之后,执行的代码")  # 只有用例执行之后的后置清理代码

Fixture has 4 scopes: test session (session), test module (module), test class (class), test case (function)

Test session: The entire process of pytest executing a test case is called a session.

For example, pytest has collected 100 use cases and executed them. This process is called a test session.

Set the scope of the fixture: set it by @pytest.fixture(scope=scope). By default, scope=function

import pytest


# 没有设置scope,默认为测试函数级别。即调用此fixture的测试类/模块/函数下,每个测试函数都会执行一次这个fixture
@pytest.fixture
def init():
    print("用例执行之前,执行的代码")  # 前置代码
    yield
    print("用例执行之后,执行的代码")  # 后置代码


# 设置scope为class。调用此fixture的测试类下,只执行一次这个fixture.
@pytest.fixture(scope="class")
def init2():
    print("用例执行之前,执行的代码")  # 只有用例执行之前的前置准备代码


# 设置scope为session。autouse表示自动使用。
# 那么在pytest收集用例后,开始执行用例之前会自动化执行这个fixture当中的前置代码,
# 当所有用例执行完成之后,自动化执行这个fixture的后置代码。
@pytest.fixture(scope="session",autouse=True)
def init3():
    yield
    print("用例执行之后,执行的代码")  # 只有用例执行之后的后置清理代

Fixture return value setting: yeild return value

When the data generated in the fixture is to be used in the test case, the fixture needs to return the data.

If there is data to return: yeild return value

import pytest
from selenium import webdriver
from time import sleep


# 设置scope为class。调用此fixture的测试类下,只执行一次这个fixture.
@pytest.fixture(scope="class")
def init2():
    print("==== 测试类下,执行所有用例之前,执行的代码 ====")
    driver = webdriver.Chrome()
    yield driver   # 返回driver对象
    print("==== 测试类下,执行所有用例之后,执行的代码 ====")
    driver.quit()

2. Call fixture

After the fixture is defined, it can be specified:

Which pre-preparation work and post-cleanup work does the
fixture handle in which scope (is it a test function? Or a test class? Or a test session? Or a test module?)
After the above two points are settled, the next step is , in the test case, call different fixtures as needed.

There are 2 calling methods:

Add above the test case/test class: @pytest.mark.usefixture("fixture function name");
use the fixture function name as the parameter of the test case function;

The second usage is mainly to use parameters to receive the return value of fixture for use in test cases

The case of the first method is as follows:

Please add a picture description

The case of the second method is as follows:

Please add a picture description

3. conftest.py sharing mechanism

In some large business scenarios, in many use cases, the same pre-preparation work and post-clearing work will be used.

If the pre-preparation work and post-clearing work are written once under each test module, it will not be good enough in terms of maintenance and optimization.

The pytest framework provides a fixture sharing mechanism that allows different use case modules to use the same fixture. This is the conftest.py file.

conftest.py shared implementation

In the project root directory, create a conftest.py file.
The file name must be conftest.py, which is case-sensitive and cannot be changed.
In conftest.py, multiple fixtures can be written
in the test case file, and there is no need to import the conftest.py file. Directly call the function name of the fixture, it will automatically go to conftest.py to find it.

Please add a picture description

conftest.py hierarchical scope
conftest.py is in the root directory of the project, all test cases under the project can use the fixture defined in conftest.py. That is, conftest.py in the project root directory, the scope is the entire project.

So, what if the fixture in conftest.py only wants to be available in a certain python package?

conftest.py implements hierarchical scope.

Simply put, it is: in which directory is conftest.py, all use cases in this directory (including subdirectories) can use the fixtures in it.

As shown below:

The fixture in conftest.py in the root directory can be used regardless of the use case under the project.
The fixture in conftest.py under the subdirectory moduleA can only be used in the use cases under moduleA.
The fixture in conftest.py under the subdirectory moduleB can only be used in the use cases under moduleB.

Please add a picture description

The use case in the use case file test_module_b.py under moduleB can use the fixture in conftest.py in the root directory, or the fixture in conftest.py in its own directory:

Please add a picture description

What if a fixture with the same name appears?

This involves the order in which the fixture is called when the test case is executed. Generally speaking, it is called according to the principle of proximity.

Fixtures in the test case file > fixtures in the current directory > fixtures in the parent directory > fixtures in the root directory

4. Fixture nesting

Fixture not only supports sharing, but also supports nesting.

Nested use means: a fixture can be used as a parameter of another fixture.

As shown in the figure below: the fixture named init2 can be used as the parameter of init.
And, in init, the return value of init2 is also returned.

Please add a picture description

When calling init in a use case, init will automatically call init2.

The execution order of the fixture is as follows:
pre-code of init2;
pre-code of init;
post-code of init;
post-code of init2;

In the case shown in the figure below, init2 is class-level scope, and init is function-level scope.

Please add a picture description

Please add a picture description

The following is the most complete software test engineer learning knowledge architecture system diagram in 2023 that I compiled

1. From entry to mastery of Python programming

Please add a picture description

2. Interface automation project actual combat

Please add a picture description

3. Actual Combat of Web Automation Project

Please add a picture description

4. Actual Combat of App Automation Project

Please add a picture description

5. Resume of first-tier manufacturers

Please add a picture description

6. Test and develop DevOps system

Please add a picture description

7. Commonly used automated testing tools

Please add a picture description

Eight, JMeter performance test

Please add a picture description

9. Summary (little surprise at the end)

As long as you have a dream, don't give up pursuing it; as long as you work hard, there will be no difficulties you cannot overcome. Every persistence will make you stronger; every step of struggle will lead you to a better future.

As long as you have a dream in your heart and move forward bravely, even if there are twists and turns and difficulties, you will not stop. Every setback is a gift of growth, and every effort is the only way to meet success. Let us create brilliance with sweat!

Bravely pursue your dreams, not afraid of difficulties and obstacles; only by working hard and indomitable can you walk on the road to success. As long as we have faith and courage, we can break through difficulties and create our own brilliance!

Guess you like

Origin blog.csdn.net/m0_70102063/article/details/130087420