0%

数据驱动测试

数据文件,驱动用例执行数量、内容

1
2
3
4
5
a,b,c
1,2,3
2,3,5
3,3,6
4,4,7
1
2
3
4
5
6
7
8
@pytest.mark.ddt
@pytest.mark.parametrize(
"a,b,c",
read_csv("study/data.csv")
)
def test_ddt(self, a, b, c):
res = add(int(a), int(b))
assert res == int(c)

夹具fixture

夹具:在用例执行之前、执行之后,自动运行代码

场景:

  • 之前:加密参数 / 之后:解密结果
  • 之前:启动浏览器 / 之后:关闭浏览器
  • 之前:注册、登陆账号 / 之后:删除账号

1.创建fixture

1
2
3
4
5
6
7
@pytest.fixture
def f():
print(datetime.now(), '用例开始执行')
# yield以上的内容为执行用例的前置操作
yield # 开始执行用例
# yield以下的内容为执行用例的后置操作
print(datetime.now(), '用例执行完毕')
  1. 创建函数
  2. 添加装饰器
  3. 添加yield关键字

2. 使用fixture

  1. 在用例的参数列表中,加入fixture名字即可
  2. 用例加上usefixture标记
1
2
3
4
5
6
def test_1(f):
pass

@pytest.mark.usefixtures("f")
def test_2():
pass

3. 高级用法

  1. 自动使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @pytest.fixture(autouse=True)
    def f():
    print(datetime.now(), '用例开始执行')
    # yield以上的内容为执行用例的前置操作
    yield # 开始执行用例
    # yield以下的内容为执行用例的后置操作
    print(datetime.now(), '用例执行完毕')

    def test_1():
    pass

    def test_2():
    pass
  2. 依赖使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @pytest.fixture
    def ff():
    print("我也是fixture,但是被fixture使用")

    @pytest.fixture(autouse=True)
    def f(ff):
    print(datetime.now(), '用例开始执行')
    # yield以上的内容为执行用例的前置操作
    yield # 开始执行用例
    # yield以下的内容为执行用例的后置操作
    print(datetime.now(), '用例执行完毕')

    def test_1():
    pass

    def test_2():
    pass
  3. 返回内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @pytest.fixture
    def ff():
    print("我也是fixture,但是被fixture使用")

    @pytest.fixture(autouse=True)
    def f(ff):
    print(datetime.now(), '用例开始执行')
    # yield以上的内容为执行用例的前置操作
    yield 1234 # 开始执行用例
    # yield以下的内容为执行用例的后置操作
    print(datetime.now(), '用例执行完毕')

    # 从python的语法看,函数中可以有多个yield,但是pytest框架中只能有一个,后续的将被丢弃

    def test_1(f):
    print('收到fixture传递的数据', f)

    def test_2():
    pass
  4. 范围共享

    当做web自动化时,打开浏览器需要3~6秒的时间,如果有上千条用例需要打开浏览器这一步操作,重复使用会导致不必要的时间浪费,因此把第一条用例打开的浏览器共享给后者则显得尤为重要。

    • 默认范围:function

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      @pytest.fixture
      def ff():
      print("我也是fixture,但是被fixture使用")

      @pytest.fixture(autouse=True, scope='function')
      def f(ff):
      print(datetime.now(), '用例开始执行')
      # yield以上的内容为执行用例的前置操作
      yield 1234 # 开始执行用例
      # yield以下的内容为执行用例的后置操作
      print(datetime.now(), '用例执行完毕')

      # 从python的语法看,函数中可以有多个yield,但是pytest框架中只能有一个,后续的将被丢弃

      def test_1(f):
      print('收到fixture传递的数据', f)

      def test_2():
      pass
    • 全局范围:session

      • 让不同文件可以共享夹具可以使用conftest.py
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      # conftest.py

      @pytest.fixture(scope='session')
      def ff():
      print("我也是fixture,但是被fixture使用")

      @pytest.fixture(autouse=True, scope='session')
      def f(ff):
      print(datetime.now(), '用例开始执行')
      # yield以上的内容为执行用例的前置操作
      yield 1234 # 开始执行用例
      # yield以下的内容为执行用例的后置操作
      print(datetime.now(), '用例执行完毕')

      # 从python的语法看,函数中可以有多个yield,但是pytest框架中只能有一个,后续的将被丢弃

      def test_1(f):
      print('收到fixture传递的数据', f)

      def test_2():
      pass

插件管理

插件分成两类:

  • 不需要安装:内置插件
  • 需要安装:第三方插件

插件的启用管理:

  • 启用:-p abc
  • 禁用:-p no:abc

插件的使用方式:

  1. 参数
  2. 配置文件
  3. fixture
  4. mark

常用第三方插件

1. pytest-html

用途:生成HTML测试报告

安装:

1
2
pip install pytest-html
conda install pytest-html

使用:

1
pytest --html=report.html --self-contained-html

可以在pytest.ini文件中添加如下参数

注意:在终端执行时的路径需要能够发现pytest.ini文件

1
2
3
[pytest]

addopts = --html=report.html --self-contained-html

2. pytest-xdist

用途:分布式执行

安装:

1
2
pip install pytest-xdist
conda install pytest-xdist

使用:

1
-n N

只有在任务本身耗时较长,超出调度成本很多的时候才有意义。

分布式执行,有并发问题:资源竞争、乱序

3. pytest-rerunfailures

用途:用例失败之后重新执行(网络不通、UI渲染等场景)

安装:

1
2
pip install pytest-rerunfailures
conda install pytest-rerunfailures

使用:

1
--rerurns 6 --reruns-delay 2

4. pytest-result-log

用途:把用例执行结果记录到日志文件中

安装:

1
2
pip install pytest-result-log
conda install pytest-result-log

使用(报错编码问题请删除注释):

1
2
3
4
5
6
7
8
9
10
11
12
13
log_file = ./logs/pytest.log_file
log_file_level = info
log_file_format = %(levelname)-8s &(asctime)s [%(name)s:%(lineno)s] : %(messgage)s
log_file_date_format = %Y-%m-%d %H:%M:%S

; 记录用例执行结果
result_log_enable = 1log_file
; 记录用例分割线
result_log_separator = 1
; 分割线等级
result_log_level_separator = warning
; 异常信息等级
result_log_level_verbose = info

企业级测试报告

allure是一个测试报告的框架

安装:

1
2
pip install allure-pytest
conda install allure-pytest

配置:

1
addopts = --alluredir=temps --clean-alluredir

生成报告:

1
allure generate -o report -c temps

一键执行:

1
2
3
4
5
6
7
#main.py

import pytest
import os

pytest.main()
os.system("allure generate -o report -c temps")

allure支持对用例分组和关联(敏捷开发术语)

1
2
3
4
@allure.epic  史诗  项目
@allure.feature 主题 模块
@allure.story 故事 功能
@allure.title 标题 用例

使用相同装饰器的用例,自动并入一组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@allure.epic('自动化测试')
@allure.feature('pytest')
@allure.story('mark标记和筛选')
@allure.title('实现筛选')
@pytest.mark.api
def test_a():
pass

@allure.epic('自动化测试')
@allure.feature('pytest')
@allure.story('fixture前置后置')
@allure.title('使用fixture')
@pytest.mark.api
def test_b():
pass