编写规范:
• 测试⽂件以 test_ 开头(以 test 结尾也可以)
• 测试类以 Test 开头,并且不能带有 init 方法!
• 测试函数以 test 开
模块级(setup_module/teardown_module)模块始末,全局的
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
| import pytest """ 开始于模块始末,全局的 setup_module teardown_module """
def setup_module(): print "setup_module():在模块最之前执行\n"
def teardown_module(): print "teardown_module:在模块之后执行"
def setup_function(): print "setup_function():每个方法之前执行"
def teardown_function(): print "teardown_function():每个方法之后执行\n"
def test_01(): print "正在执行test1" x = "this" assert 'h' in x
def add(a,b): return a+b
def test_add(): print "正在执行test_add()" assert add(3,4) == 7
|
函数级(setup_function/teardown_function)只对函数用例生效,而且不在类中使用
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
| import pytest
def setup_function(): print "setup_function():每个方法之前执行"
def teardown_function(): print "teardown_function():每个方法之后执行"
def test_01(): print "正在执行test1" x = "this" assert 'h' in x
def test_02(): print "正在执行test2" x = "hello" assert hasattr(x,"hello")
def add(a,b): return a+b
def test_add(): print "正在执行test_add()" assert add(3,4) == 7
if __name__=="__main__": pytest.main(["-s","test_function.py"])
|
类级(setup_class/teardown_class)在类中使用,类执行之前运行一次,类执行之后运行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import pytest
class TestClass(object):
def setup_class(self): print "setup_class(self):每个类之前执行一次"
def teardown_class(self): print "teardown_class(self):每个类之后执行一次"
def add(self,a,b): print "这是加法运算" return a+b
def test_01(self): print "正在执行test1" x = "this" assert 'h' in x
def test_add(self): print "正在执行test_add()" assert self.add(3, 4) == 7
|
⽅法级(setup_method/teardown_methond)运⾏在类中⽅法始末
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
| import pytest
class TestMethod(object):
def setup_class(self): print "setup_class(self):每个类之前执行一次\n"
def teardown_class(self): print "teardown_class(self):每个类之后执行一次"
def setup_method(self): print "setup_method(self):在每个方法之前执行"
def teardown_method(self): print "teardown_method(self):在每个方法之后执行\n"
def add(self,a,b): print "这是加法运算" return a+b
def test_01(self): print "正在执行test1" x = "this" assert 'h' in x
def test_add(self): print "正在执行test_add()" assert self.add(3, 4) == 7
|
执行
pytest/py.test(终端,命令⾏,pycharm都⾏,可配置pycharm使⽤pytest⽅式执⾏)
pytest –v (最⾼级别信息—verbose)
pytest -v -s ⽂件名 (s是带控制台输出结果,也是输出详细)
pytest将在当前⽬录及其⼦⽬录中运⾏test _ * .py或* test.py形式的所有⽂件。
以test_开头的函数,以Test开头的类,以test_开头的⽅法。所有包package都要有init.py⽂件。
Pytest可以执⾏unittest框架写的⽤例和⽅法
1 2 3 4 5 6 7 8 9 10 11 12
| pytest -v src/testcases/api/test_autouse.py
pytest -v src/testcases/api/test_autouse.py::TestSample pytest -v src/testcases/api/ test_autouse.py::TestSample::test_answer
pytest -v src/testcases/api!
pytest -m P0 src/testcases/api/
pytest.main(['-v', '--instafail', 'testcases/api/test_example.py', '-m=P2'])
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # pytest执⾏⽤例出错时停⽌ pytest -x -v -s test.py --maxfail=2 # pytest通过⽂件名类名⽅法及组合调⽤部分⽤例执 # 直接输⼊⽂件名,类名 pytest test_class_01.py pytest -v -s test_class_01.py pytest -v test_class_01.py::TestClass pytest -v test_class_01.py::TestClass::test_one # 使⽤-k TestClass是类名,and是运算符,还可以是and not…,test_one是⽅法名中含有的信息 pytest -k "TestClass and test_one" pytest -k "TestClass or test_one" # mark标记执⾏ # 在测试⽤例⽅法上加@pytest.mark.webtest,-s参数: 输出所有测试⽤的print信息 -m:执⾏⾃定义标记的相关⽤例 pytest -s test.py -m=webtest
|
log
1 2 3 4 5 6 7 8 9
| 建立这个文件Pytest.ini [pytest] log_cli = 1 log_cli_level = info log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s) log_cli_date_format=%Y-%m-%d %H:%M:%S 写测试用例————log.info() 用: pytest pytest_testlog.py -o log.cli=true -o log._cli_level=INFO -o是覆盖配置的内容
|
插件
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
| # pytest-html ⽣成可视化报告,--self-contained-html(把css样式合并到html) pytest -v -s --html=report.html --self-contained-html
# pytest-assume 多条断⾔有失败也都运⾏ pytest.assume(1==4) pytest.assume(2==4)
# pytest-rerunfailures 失败重跑 —reruns n, n是重复次数 pytest --reruns 5 test_sort_demo.py
pytest-allure #⾼⼤上精美报告
pytest-xdist #并⾏运⾏多个测试 pytest -n 2 在2个cpu上运⾏测试 —looponfail标志,它将⾃动重新运⾏你的失败测试 pytest -n 3
Pytest-sugar # 改变pytest的默认外观,增加进度条,安装后即可
Pytest-picked # 运⾏基于你已修改但尚未提交给git的代码的测试。
Pytest-instafail # 修改默认⾏为,以⽴即显⽰失败和错误,⽽不是等到pytest完成每个测试运⾏。
Pytest-tldr # 简化man指令帮助文档
Pytest-django # 开发web
Pytest-selenium # pytest 提供运⾏⽀持selenium为基础
pytest-ordering # 顺序编排
|
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
import pytest @pytest.fixture() def loginandlogout(): print('do login action\n') yield print("do logout action") class TestSample: def test_answer(self,loginandlogout): ... def test_answer2(self,loginandlogout): ...
import pytest @pytest.fixture() def loginandlogout(): print('do login action\n') yield print("do logout action") class TestSample: @pytest.mark.usefixtures('loginandlogout') def test_answer(self): ...
@pytest.fixture(scope='module',autouse=True) def loginandlogout(): print('do login action\n') yield print("do logout action\n") @pytest.fixture(scope='class',autouse=True) def clickhome(): print('click home button\n') yield print("end click home link\n") class TestSample: def test_answer(self): def test_answer2(self): class TestSampleTwo: def test_two_answer(self):
@pytest.fixture(params=[1, 2, 3, 'bq'])
@pytest.mark.parametrize()
@pytest.mark.parametrize(“login_r”,test_user_data, indirect=True) indeirect=True是把login_r当作函数去执⾏
@pytest.mark.skip
@pytest.mark.xfail
|
钩子函数
获取用例执行结果处理用例依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import pytest
class Falied: skip = False @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_runtest_makereport(): result = yield report = result.get_result() case_name = report.nodeid.split('::')[-1] if report.when in ('setup', 'call') and report.outcome in ('failed', 'skipped'): setattr(Falied, case_name, True) if __name__ == '__main__': pytest.main(['-s', '-q'])
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import pytest from .conftest import Falied class TestDemoA: def test_A_001(self): assert 0 def test_A_002(self): if getattr(Falied, 'test_A_001', False): pytest.skip('test_A_001 执行失败或被跳过,此用例跳过!') def test_A_003(self): pass
|
report
生成 JunitXML 格式的测试报告,命令 : –junitxml= path
生成 ResultLog 格式的测试报告,命令: –resultlog=report/log.txt
生成 Html 格式的测试报告,命令: –html=OutPuts/reports/report.html (相对路径)
1
| pytest --html=report/html/report.html testcase/test_new_outfit.py::TestNewOutfit::test_newoutfit_normal
|