[h2]今天来介绍下pytest和断言,在测试中断言很重要能够及时的验证你所操作的能否达到你预想的结果,断言和异常还不太一样,断言有时可以说是一个if-else的表达式的返回的结果,如果表达式为false则进行触发异常,然后在简单的介绍下pytest吧,pytest和unitest都是测试的框架可以快速的测试,在pytest测试函数中是按照你写的测试方法的顺序进行执行的而unitest是按照你测试方法的首字母(根据英文26个字母的顺序)的顺序执行的。[/h2][h2]断言(assert)[/h2]Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常。允许您使用标准python来验证Python测试中的期望值和值
语法格式如下:
assert expression等价于:
if not expression: raise AssertionErrorassert 后面也可以紧跟参数:
assert expression [, arguments]等价于:
if not expression: raise AssertionError(arguments)def test_updatet_other(begin): engagement_page.click_update_items_first() # 选择第一条 engagement_page.click_btn1_all() edit_other_page.click_other_input('other update') # 更新 edit_other_page.click_submit_btn() engagement_page.should_no_red_icon() other_name = engagement_page.get_first_item_content_text() assert other_name == "Other update" engagement_page.click_delete_first_note()
[h2]pytest[/h2]是一个框架,使构建简单和可伸缩的测试变得容易。测试具有表现力和可读性 - 无需样板代码。通过针对您的应用程序或库的小型单元测试或复杂功能测试,在几分钟内开始使用。
[h3]安装[/h3]pip install -U pytest$ pytest --versionThis is pytest version 5.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py[h3]创建你的第一个测试[/h3]使用四行代码创建一个简单的测试函数:
# content of test_sample.pydef func(x): return x + 1def test_answer(): assert func(3) == 5一旦开发了多个测试,您可能希望将它们分组到一个类中。pytest可以很容易地创建一个包含多个测试的类:
# content of test_class.pyclass TestClass(object): def test_one(self): x = "this" assert 'h' in x def test_two(self): x = "hello" assert hasattr(x, 'check')# coding=utf-8import pytestfrom page.LoginPage import LoginPagefrom util.ConfigUtil import ConfigUtilfrom util.ApiUtil import ApiUtil@pytest.fixture(scope="session", autouse=True)def begin(): api_util = ApiUtil() account = api_util.create_account() username = account["agencyOwner"]["userName"] password = account["agencyOwner"]["password"] print username login_page = LoginPage() login_page.login(username, password)"""执行当前目录下面的可以进行全部测试"""if __name__ == '__main__': pytest.main()#调用pytest.main()将导致导入测试及其导入的任何模块。由于python导入系统的缓存机制,pytest.main()从同一进程进行后续调用不会反映调用之间对这些文件的更改。因此,pytest.main()不建议从同一进程进行多次调用(例如,为了重新运行测试)[h3]对于@pytest.fixture()的用法有:[/h3]对于scope可能的值有:,,,或。
直接说一下吧:
session在一次Run或Debug中执行的所有case共享一个session,第一个case开始执行的时候session开始,最后一个case执行结束的时候session结束,这些case可能分布在不同的class或module中。module一个.py文件可以看作一个module,其表示的范围指该文件中第一个case到最后一个case之间的范围class表示的范围即class的范围 一个类中执行一次function表示的范围即function的范围 每次都会执行一次下一个示例将fixture函数放入单独的文件中,以便来自目录中多个测试模块的测试可以访问fixture函数:
# content of conftest.pyimport pytestimport smtplib@pytest.fixture(scope="module")def smtp_connection(): return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)源码:
def fixture(scope="function", params=None, autouse=False, ids=None, name=None): :arg scope: the scope for which this fixture is shared, one of ``"function"`` (default), ``"class"``, ``"module"``, ``"package"`` or ``"session"``. ``"package"`` is considered **experimental** at this time. :arg params: an optional list of parameters which will cause multiple invocations of the fixture function and all of the tests using it. The current parameter is available in ``request.param``. :arg autouse: if True, the fixture func is activated for all tests that can see it. If False (the default) then an explicit reference is needed to activate the fixture. :arg ids: list of string ids each corresponding to the params so that they are part of the test id. If no ids are provided they will be generated automatically from the params. :arg name: the name of the fixture. This defaults to the name of the decorated function. If a fixture is used in the same module in which it is defined, the function name of the fixture will be shadowed by the function arg that requests the fixture; one way to resolve this is to name the decorated function ``fixture_`` and then use ``@pytest.fixture(name='')``. """ if callable(scope) and params is None and autouse is False: # direct decoration return FixtureFunctionMarker("function", params, autouse, name=name)(scope) if params is not None and not isinstance(params, (list, tuple)): params = list(params) return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)具体其他的用法请看官网吧https://docs.pytest.org/en/latest/usage.html#cmdline
[h3]前置条件,后置条件[/h3]模块级别的前置条件和后置条件如果在单个模块中有多个测试函数和测试类,则可以选择实现以下fixture方法,这些方法通常会针对所有函数调用一次:
def setup_module(module): """ setup any state specific to the execution of the given module."""def teardown_module(module): """ teardown any state that was previously setup with a setup_module method. """从pytest-3.0开始,参数是可选的。
类级别前置和后置条件类似地,在调用类的所有测试方法之前和之后,在类级别调用以下方法:
@classmethoddef setup_class(cls): """ setup any state specific to the execution of the given class (which usually contains tests). """@classmethoddef teardown_class(cls): """ teardown any state that was previously setup with a call to setup_class. """方法和功能级别前置和后置条件同样,围绕每个方法调用调用以下方法:
def setup_method(self, method): """ setup any state tied to the execution of the given method in a class. setup_method is invoked for every test method of a class. """def teardown_method(self, method): """ teardown any state that was previously setup with a setup_method call. """从pytest-3.0开始,参数是可选的。
如果您希望直接在模块级别定义测试函数,还可以使用以下函数来实现fixture:
def setup_function(function): """ setup any state tied to the execution of the given function. Invoked for every test function in the module. """def teardown_function(function): """ teardown any state that was previously setup with a setup_function call. """从pytest-3.0开始,参数是可选的。
这些pytest的操作只是冰山一角,具体深入了解可以去官网学习,不过全是英文的用翻译之后很多与原文的表达不太一致,所以仍需靠大家自己去自己探索,在探索中寻求答案,在探索中实践。在后序的文章中偶会举出一些实例供大家参考,这些实例中实际的项目中得到了一定的验证,值得学习的,敬请期待后序的文章吧,觉得文章不错的请点个再看吧。
|
|