一、pytest.mark的基本用法
pytest.mark是pytest框架提供的一个非常有用的机制,它可以用来标记单个或多个测试用例。它可以提高测试用例的可读性,也可以让我们快速地选择在单次运行中执行的用例。
import pytest @pytest.mark.login def test_login(): pass @pytest.mark.register def test_register(): pass @pytest.mark.login @pytest.mark.register def test_homepage(): pass
上面的示例中,我们定义了三个测试用例。第一个测试用例用@pytest.mark.login进行了标记,第二个测试用例用@pytest.mark.register进行了标记,第三个测试用例同时用了这两个标记。
我们可以通过pytest -m选项来运行标记过的用例。例如,pytest -m login将只运行用@pytest.mark.login标记的用例。
此外,我们还可以在fixture中使用标记来指定该fixture适用于哪些测试用例。我们可以在fixture函数定义中添加相关的装饰器,来指明适用于哪些标记。例如:
import pytest @pytest.fixture @pytest.mark.login def login_data(): return {'username': 'testuser', 'password': '123456'} @pytest.fixture @pytest.mark.register def register_data(): return {'username': 'newuser', 'password': '654321'}
上面的示例中,我们定义了两个fixture。第一个fixture用@pytest.mark.login标记,第二个fixture用@pytest.mark.register标记。这意味着,当我们在运行用@pytest.mark.login标记的测试用例时,pytest会自动检测出login_data这个fixture,并将其作为参数传递给测试用例。
二、使用自定义标记来组织测试用例
除了使用官方提供的@pytest.mark外,我们还可以使用自定义的标记来组织测试用例。这样可以让我们更灵活地组织测试用例,以适应不同的测试需求。
使用自定义标记也非常简单,我们只需要在conftest.py文件中定义fixture即可。例如:
import pytest @pytest.fixture(scope='session') def api_client(): return APIClient() @pytest.fixture def user(): return User() def pytest_configure(config): config.addinivalue_line('markers', 'api: mark test as API test') config.addinivalue_line('markers', 'ui: mark test as UI test')
上面的示例中,我们定义了两个fixture:api_client和user。同时,在pytest_configure函数中,我们用config.addinivalue_line方法为pytest添加了两个自定义标记:api和ui。
现在我们可以在测试用例中使用这些标记了。例如:
@pytest.mark.api def test_create_user(api_client, user): api_client.create_user(user) @pytest.mark.ui def test_login_ui(): LoginPage().login('testuser', '123456') HomePage().assert_user_name('testuser')
在上面的示例中,我们定义了两个测试用例。第一个用@pytest.mark.api标记,这意味着这是一个API测试用例,需要使用api_client和user这两个fixture。第二个用@pytest.mark.ui标记,这意味着这是一个UI测试用例。
三、使用参数化标记来优化测试用例
pytest还提供了一个非常方便的@pyteest.mark.parametrize标记,用于参数化测试。它可以让我们轻松地运行多组测试数据,从而减少测试用例的编写量。
使用@parametrize标记也非常简单,我们只需要在测试用例函数上添加该标记,并将测试数据以及期望结果作为参数传递进去即可。例如:
import pytest @pytest.mark.parametrize(('username', 'password'), [ ('testuser', '123456'), ('newuser', '654321') ]) def test_login(username, password): result = login(username, password) assert result == 'success'
上面的示例中,我们使用了@parametrize标记,以测试两组登录数据。pytest会自动运行两次测试用例,并将每组数据作为参数传递给测试用例函数。
四、使用skip和xfail标记来优化测试用例
有时候,我们会遇到一些测试用例暂时无法通过的情况。这时候,如果我们每次都运行这些无法通过的用例,会浪费很多时间。pytest提供了两个非常有用的标记:skip和xfail,可以用来标记暂时无法通过的测试用例。
使用@skip标记,可以让pytest跳过一个测试用例。例如:
import pytest @pytest.mark.skip(reason='Test case not ready yet') def test_advanced_search(): pass
上面的示例中,我们使用了@skip标记,并填写了一个说明,以告诉pytest这个用例是有问题的,应该跳过它。
使用@xfail标记,可以让pytest把一个无法通过的测试用例当成一个预期失败的用例来处理。例如:
import pytest @pytest.mark.xfail(reason='Bug not yet fixed') def test_add_bug(): add_bug() assert len(get_bugs()) == 0
上面的示例中,我们使用了@xfail标记,并填写了一个说明,以告诉pytest这个用例是无法通过的,但是是预期失败的。
五、使用fixture的autouse参数来自动运行fixture
pytest的fixture机制非常灵活,可以让我们在测试用例中自由地组织数据和逻辑。同时,我们还可以使用fixture的autouse参数来自动运行fixture。
使用autouse参数很简单,只需要在fixture函数定义时添加该参数即可。例如:
import pytest @pytest.fixture(autouse=True) def setup(): login() yield logout()
上面的示例中,我们定义了一个fixture,它用于执行登录和注销操作。我们把autouse参数设置为True,这意味着这个fixture会在每个用例执行前后自动运行。
这样的好处是显而易见的。我们不用在每个用例中都手动添加登录和注销的逻辑,而是可以把它们封装到fixture中,让每个用例都自动调用这个fixture。这样可以提高测试用例的可读性和可维护性,也可以让我们专注于测试用例本身,而不用过多关注登录和注销。