pytest 使用

pytest的使用

安装

pip install pytest

pytest 测试发现约定

  1. 如未指定任何参数,则收集从testpaths (如果已配置:可以通过pytest.ini配置文件发现路径,配置文件只在当前目录下生效),或当前目录开始。
    pytest.ini文件
[pytest]
testpaths = testing doc

注意格式:用例发现路径用空格隔开,关键字不能写错

  1. 命令行参数可以在目录,文件名或者节点ID的任何组合中使用。
if __name__ == '__main__':
    # pytest.main(['-s'])  # '-s' 表示输出打印信息,pytest默认是不输出打印信息的
    pytest.main(['-s','./testing/test_demo1.py::test_001'])
  1. 在当前目录及其子目录中运行所有格式为test_.py或者_test.py文件,从这些文件中收集测试项目。
  • 类之外拥有test前缀的测试函数或方法
    test_demo1.py
def test_demo1():
    print("hello world")
  • 在拥有Test前缀中的测试类(不含_init_方法)中的拥有test前缀的测试函数或方法
    test_demo2.py
class TestDemo():
    #测试 方法
    def test_range_match(self,kdtid,expected):
    	print("hello world")
  1. 可以自定义测试发现规则,比如忽略掉一些目录
if __name__ == '__main__':
    # 自定义测试发现规则,比如忽略掉一些目录
    pytest.main(['-s', '--ignore=testing/', '--ignore=doc/'])
  1. pytest也可以发现使用标准的unittest.TestCase子类技术的测试用例(完全兼容unittest)

pytest参数化

当一组测试用例有固定的测试数据时,就可以通过参数化的方式简化测试用例的编写。通过pytest.mark.parametrzie()方法设置参数:

  • 参数名:"user,pw,expected"用来定义参数的名称
  • 参数值:通过数组定义参数值时,每一个元祖都是一条测试用例的测试数据
  • ids参数:默认None,用来重新定义测试用例的名称
@pytest.mark.parametrize(
   "user,pwd,expected",
   [( "test1","aaa","ok"),
    ( "test2","bbb","false"),
    ( "test3","ccc","unknow")],
    ids=["test_case1","test_case2","test_case3"]
    )
def test_parametrize(user,pwd,expected):
    print(user,pwd,expected)

pytest中的setup和tearDow

有些测试用例需要在跑测试case前先初始化一下数据,当测试case 结束的时候就需要清理一下测试环境的数据。在java 中存在 @BeforeClass,@AfterClass pytest 中也存在

import pytest

def setup_module(module):
    """
    这是一个module级别的setup,它会在本module(test_website.py)里
    所有test执行之前,被调用一次。
    注意,它是直接定义为一个module里的函数"""
    print()
    print("-------------- setup before module --------------")


def teardown_module(module):
    """
    这是一个module级别的teardown,它会在本module(test_website.py)里
    所有test执行完成之后,被调用一次。
    注意,它是直接定义为一个module里的函数"""
    print("-------------- teardown after module --------------")

# Test前缀中的测试类
class TestDemo1(object):
    def test_login(self):
        print("test baidu login function")
        assert True == True
class TestSohu(object):

    @classmethod
    def setup_class(cls):
        """ 这是一个class级别的setup函数,它会在这个测试类TestSohu里
        所有test执行之前,被调用一次.
        注意它是一个@classmethod
        """
        print("------ setup before class TestSohu ------")

    @classmethod
    def teardown_class(cls):
         """ 这是一个class级别的teardown函数,它会在这个测试
         类TestSohu里所有test执行完之后,被调用一次.
        注意它是一个@classmethod
        """
        print("------ teardown after class TestSohu ------")

    def setup_method(self, method):
        """ 这是一个method级别的setup函数,它会在这个测试
         类TestSohu里,每一个test执行之前,被调用一次.
        """
        print("--- setup before each method ---")
    
    def teardown_method(self, method):
        """ 这是一个method级别的teardown函数,它会在这个测试
         类TestSohu里,每一个test执行之后,被调用一次.
        """
        print("--- teardown after each method ---")

    def test_login(self):
        print("sohu login")
        assert True == True

    def test_logout(self):
        print("sohu logout")
        pytest.skip()

pytest.ini 配置文件

将这个配置文件放在项目目录的最外层

[pytest]

 ; 命令行窗口日志输出配置
 ; log_cli 可以输入0, False 代码不输出日志, 1、True 代表开启日志输出
 ; log_cli_level 代表日志输出级别
 ; log_cli_date_format 日期格式
 ; log_cli_format 日志模板格式

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_file 日志文件
 ; log_file_level 代表日志输出级别
 ; log_file_date_format 日期格式
;  log_file_format 日志模板格式
log_file=outputs/logs/test.log
log_file_level=INFO
log_file_date_format=%Y-%m-%d %H:%M:%S
log_file_format=%(asctime)s %(filename)s %(module)s %(funcName)s %(lineno)d %(levelname)s: %(message)s

; 在配置文件中加上启动参数选项
; -v 详细信息, -s 打印信息 
; --reruns=1 --reruns-delay=5 表示失败延迟5秒重新运行一次,需要 pip install  pytest-rerunfailures
; --html=reports.html --self-contained-html 生成html 报告 pip install  pytest-html
addopts = -v -s --reruns=1 --reruns-delay=5 --html=reports.html --self-contained-html

运行测试用例

pytest 存在两种方式运行测试用例,一种是使用pytest 命令 一种是卸载 main 函数中

命令行的方式运行

#指定测试方法,当前项目目录下的demo_test.py的TestDemo是类,test_demo1 是测试方法
pytest  py-test/demo/demo_test.py::TestDemo::test_demo1
# 如果没有类的话也可以直接指定方法
pytest  py-test/demo/demo_test.py::test_demo2
# --pdb 当测试方法遇到错误的时候会中断,可以进行调试
pytest --pdb py-test/demo/demo_test.py::TestDemo::test_demo1

代码中执行

if __name__ == '__main__':
    pytest.main(['-s','py-test/demo/demo_test.py::TestDemo::test_demo1'])

参考

pytest测试框架中的setup和tearDown

上一篇:寄存器模型(RAL,Register Abstraction Layer)——UVM


下一篇:pytest