See You Again

pytest自动化测试框架实践

最近一个项目的自动化测试框架用的是 pytest,用起来感觉跟 python 一样,简单、灵活、易用,相比于RF学习成本会低一点,因为它是直接写python代码的。至于其他优点可以去官网看看,对于常规的单元、功能、接口测试等基本都可以考虑。
这里结合具体的项目实践,让大家对 pytest 有一个感性的认识。

安装

首先安装好 python 环境,然后装一个库即可:

  1. pip install -U pytest

执行案例

可以在命令行下执行用例,也可以通过 IDE (例如 pycharm)运行。用例的选择也是很灵活的,可以是单个用例、模块里的用例、标签、文件夹下的用例,下面分别介绍:

命令行运行

  1. py.test test_mod.py # run tests in module
  2. py.test somepath # run all tests below somepath
  3. py.test -k stringexpr # only run tests with names that match the "string expression", e.g. "MyClass and not method" will select TestMyClass.test_something but not TestMyClass.test_method_simple
  4. py.test test_mod.py::test_func # only run tests that match the "node ID", e.g "test_mod.py::test_func" will select only test_func in test_mod.py
  5. py.test test_mod.py::TestClass::test_method # run a single method in a single class

更丰富的命令行选项可以看帮助,常用的是生成测试报告,例如--html=./report.html--junitxml=./log.xml, 当然也可以在模块内自动调用:

  1. if __name__ == '__main__':
  2. pytest.main() #执行当前文件所在的目录下的所有测试文件。
  3. pytest.main("-q test_mod.py") # 指定测试文件
  4. pytest.main("D:/git/pydemo/tests/") # 指定测试目录

IDE

如果通过 pycharm,配置好之后,可以直接在对应的函数、模块、文件夹等通过右键去运行:

写案例

在 pytest 中案例的最小单位是函数/类,只要按照一定的命名规范即可:

pytest会在跑案例之前把满足这些特征的用例筛选出来,然后运行。具体实现还需要研究代码。

结果判断

框架基本都会提供一种机制帮助判断程序运行结果是否符合预期,从而决定案例是否通过。pytest 直接使用 python
的 assert 语句,所以以下各种写法都是OK的:

  1. demo_str = 'hello world'
  2. assert 'wor' in demo_str
  3. assert demo_str.startswith('hello')
  4. assert hasattr(demo_str, '__sizeof__')
  5. assert 4 == 4.0
  6. assert 5 > 4
  7. assert re.match('hello \d+', 'hello 9527')
  8. assert 'x' in json.loads('{"x":1, "y":2}')
  9. assert True

另外,pytest还提供了异常捕获的机制:

  1. def test_demo_exceptions():
  2. with pytest.raises(ZeroDivisionError):
  3. 1 / 0
  4. with pytest.raises(IndexError):
  5. (5, 10, 15)[30]

setup/teardown

这个有点难用中文表达,大概意思就是在测试执行前/后做一些初始化/清理操作,pytest也提供了较全面的支持

  1. # 本模块所有案例之前执行一次;典型场景:造数据、初始化客户端等
  2. def setup_module(module):
  3. print ("\nsetup_module ===>")
  4. # 本模块所有案例之后执行一次
  5. def teardown_module(module):
  6. print ("\nteardown_module ===>")
  7. # 每个测试函数前执行
  8. def setup_function(function):
  9. print ("\nsetup_function ->")
  10. # 每个测试函数后执行
  11. def teardown_function(function):
  12. print ("\nteardown_function ->")

这个机制基本每个测试框架都会提供,pytest 还提供一种特殊的机制 fixture,把一些公共的调用过程(例如连接DB、登录、创建临时文件)通过函数参数自动创建,这些调用过程可以在一定范围内共享(function, cls, module, session)。例如内建的创建临时文件夹tmpdir

  1. def test_demo_fixture(tmpdir):
  2. print tmpdir
  3. assert tmpdir

运行后会发现这个案例是可以通过的,而且 tmpdir 是有值的,原因是 pytest 把 tmpdir 实现为了一个 fixture,当作为函数参数时就会被运行。自己实现一个 fixture 也很简单,使用修饰器 @pytest.fixture()

数据驱动

pytest 内置了支持,即可以参数化的形式运行案例:

  1. @pytest.mark.parametrize(
  2. "expr, expected", [
  3. ('8 * 10', 80),
  4. ('2 + 5', 7),
  5. ('2 / 5.0', 0.4),
  6. ('2 / 5', 0),
  7. ('2 - 5', -3),
  8. ('100 / 5', 20)
  9. ])
  10. def test_demo_parametrize(expr, expected):
  11. assert eval(expr) == expected

多个参数可以进行组合

  1. @pytest.mark.parametrize("x", [5, 1])
  2. @pytest.mark.parametrize("y", [2, 3])
  3. def test_demo_multi_param(x, y):
  4. print x * y

持续集成

自动化机制建立起来后,最好进行持续构建,便于跟踪和及时发现问题,例如常用的 jenkins:

其他

本文介绍了常用的一些实践,帮助入门者进行了解,一些高级的用法或技巧后面再去介绍。最后写几点编写自动化案例的最佳实践:

2018-04-27 喜欢

Copyright © 2015-2018 转载请注明出处

回到顶部 ↑