51Testing软件测试论坛

标题: 移动端自动化测试系列之二——pytest入门详解 [打印本页]

作者: 巴黎的灯光下    时间: 2017-6-30 13:56
标题: 移动端自动化测试系列之二——pytest入门详解
前言
pytest是一个方便去写测试用例的测试框架.由于一开始我也不太清楚python有哪些比较好的测试框架,所以在写框架之前先调研了一些常见的测试框架.

.Unittest
.Doctest
.pytest
.nose

最终我倾向于nose和pytest,在进一步的了解这两款测试框架的api之后,最终选用了pytest,原因是使用起来真的非常简单.而且对Allure支持的非常好,这是后话了.我们先来看看pytest到底怎么使用吧.

这里我使用的IDE是:pycharm,非常好用.建议下载一个使用.尤其是对应python新手.

pytest 安装

  1. pip3 install pytest
复制代码
或者设置Pycharm的工程解释器来安装

进入Preferences:

pytest 使用

sample-run
创建一个 sample.py 文件
  1. # content of sample.py
  2. def test_answer():
  3.    assert 1 + 2 == 3
复制代码
执行
  1. py.test sample.py
  2. 或者
  3. pytest sample.py
复制代码

可以发现用例执行成功.

上述命令可以使pytest自动查找 sample.py 文件下所有的格式为:test_*的方法,然后执行用例.执行顺序为方法的顺序.

如果有多个py文件,可以直接使用下面命令
  1. pytest
复制代码
这个命令会找出当前目录下所有格式为test_*.py 或 *_test.py的文件然后执行用例.上面我们定义的文件名为sample.py,所以如果使用pytest是找不到用例的,我们需要把名称改成test_sample.py或者sample_test.py

注意文件内的方法名必须是test_*这种类型.如果写成def answer_test() 也是找不到的.
查找规则见文档: test-discovery

输出日志
在测试用例中输出日志,是常见的场景,如下
  1. # content of test_sample.py
  2. class TestSample:
  3.    def test_answer(self):
  4.        print('this is a log')
  5.        assert 1 + 2 == 3
复制代码
然后执行py.test sample.py是不会输出日志的.需要加上-s参数.同时建议也加上-q参数.即quiet 报道模式,这样输出会好看点.
  1. pytest test_sample.py -s -q
复制代码

fixtures
说到测试框架自然要说到setup和teardown两个方法.

setup是用来做准备操作.一般用来初始化资源.
teardown是用来做收尾操作.一般用了关闭资源.
pytest的setup和teardown是利用@pytest.fixture这个注释来完成的.不仅可以完成初始化操作,初始化后如果有数据需要给用例使用也是非常方便!

setup
直接来看下面代码.
  1. # content of test_sample.py
  2. import pytest
  3. class TestSample:
  4.    @pytest.fixture()
  5.    def count(self):
  6.        print('init count')
  7.        return 10
  8.    def test_answer(self, count):
  9.        print('get count %s' % count)
  10.        assert count == 10
复制代码
执行结果:

通过@pytest.fixture() 注释会在执行测试用例之前初始化操作.然后直接在测试用例的方法中就可以拿到初始化返回的参数(参数名要和初始化的方法名一样)

OK,假如我们新增一个方法会怎么样?
  1. # content of test_sample.py
  2. import pytest
  3. class TestSample:
  4.    @pytest.fixture()
  5.    def count(self):
  6.        print('init count')
  7.        return 10
  8.    def test_answer(self, count):
  9.        print('test_answer get count %s' % count)
  10.        assert count == 10
  11.    def test_answer_2(self, count):
  12.        print('test_answer_2 get count %s' % count)
  13.        assert count == 10
复制代码

可以发现 init count 这条日志输出两遍,也就是执行了两次初始化.这并没有什么问题.但是有时候我们希望的一个全局的初始化,既我们希望在这个类中只会执行一次这个初始化该怎么做?

fixture 有一个域(scope)的概念,用来指定该 fixture 的使用范围.

这里有五种域: module/class/session/invocation/function(default).


为了简单测试,这里我们修改一下工程目录结构,并且把fixture专门放到一个文件中方便使用:

通过下面命令可以列出当前目录中查找出来的所有 fixture
  1. pytest --fixtures
  2. 或者
  3. pytest --fixtures [目录]
复制代码

这里有个坑,就是虽然这里发现了 count 这个fixture,但在跑case的时候会报错说找不到!

原因是写 fixture 的文件的文件名不能瞎比写啊(捂脸),必须叫做 conftest.py

改完文件名后我们在运行:

这是在使用 seesion 域的情况下,可以发现init只执行一次.假如我们需要这种情况,每一个类都执行一次init,那么很简单直接把域改成 class 即可,同理 module 是基于模块的.有兴趣可以都去尝试一下.这里就不细说了.

teardown
利用python 的语法 yield 即可.
  1. # content of conftest.py
  2. import pytest
  3. @pytest.fixture(scope="session")
  4. def count():
  5.        print('init count')
  6.        yield 10
  7.        print('teardown count')
复制代码
执行结果

代码中执行用例
有些时候需要在代码中调用执行case的方法.而不是通过command的方式.我们可以在python代码中加入下面代码即可:
  1. args = ['-s', '-q']
  2. pytest.main(args)
复制代码



作者: sinxsiny    时间: 2017-7-8 15:57
谢谢谢谢谢谢,学习啦
作者: 赵佳乐SMILE    时间: 2019-4-16 08:34
学习了




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2