我的日常工作
我所工作的组是一个QA组,负责测试我们整个开发组所研发的所有工具的测试。在我们的日常的工作中主要负责的内容是:
- Regular QA on projects:手动测试新功能,跟踪Issue
- API tests: 测试项目的一些接口,由于我所参与的项目大多是Rest API, 所以我们会用到Postman,SoapUI等工具进行 API的automation测试。
- UI automation tests: 当项目已经有稳定的UI时,我们就会考虑开发UI的自动化测试脚本来进行regression 测试以适应软件的快速迭代。
今天我想来分享一些我做UI automation测试的点。在我们组我们都是用selenium框架进行UI自动化测试,之前别的项目采用的是Java+TestNG+ExtentReport,如果我沿用这一套框架的话,那么我可能只需要复制其中很多模块就可以快速的构建这个测试脚本用于新的项目。但是当时我并没有这么做,主要的原因是:
- 我习惯于用Python来开发自动化脚本,而且我之前有用python开发自动化测试脚本的经验。
- 如果我用Java的那一套框架,那么很有可能我对里面的细节并没有很好的理解,而且我的大部分时间都会花在学习Java的语法上。
- 我找到了一套可以和Java媲美的用Python来实现的一套框架,那就是:Pytest+Allure
基于上面的这些考虑,我勇敢的向我的老板表达了我的想法。在和老板聊之前,我觉得老板有一定概率是会拒绝的,因为即使我可以用python来实现我的目标,但是这套框架对于我们组来说毕竟是新的,没有人用过,就代表着我需要花一定的学习时间来完成。在很多公司这些额外的学习时间往往是不被允许的。幸运的是,我的老板Anne Marie, 一如既往的支持了我的想法,她很鼓励我用我喜欢的方式来完成工作项目。于是我的第一步就顺利的通过了。接下来我就来详细的分享我的实现方法。
Pytest:a mature full-featured Python testing tool
由于我用python的unittest框架开发过一个测试脚本,所以一开始我是打算用unittest的框架。但是在查找资料的过程中发现很多人会用pytest,抱着试一试的态度我也开始用了起了pytest。但是刚开始我还是没有完全摆脱unittest的思维,沿用了里面的setUp/tearDown方法,中间并没有发现pytest的优点,一度差点要放弃。就在我阅读文档的过程中,我发现了pytest支持Parameterizing tests,但是用unittest的框架不能用这个功能。所以最后我觉得重新写我的测试脚本,彻底放弃unittest的思维。于是这个时候我发现pytest简直太好用了。
why pytest
- Comprehensive online and PDF documents and comes with many tests examples: 当你开始学习的时候,你会发现有非常详细的文档可以查阅,而且有非常多的实例,这一点对于一个初学者来说简直不要太好。
- Powerful fixtures: 对我来说,fixtures是一个挺抽象的词的,但是大致可以理解为是一个function的意思。文档中对fixture的定义是“The purpose of test fixtures is to provide a fixed baseline upon which tests can reliably and repeatedly execute. pytest fixtures offer dramatic improvements over the classic xUnit style of setup/teardown functions”,所以可以简单的认为fixture是一些需要反复执行,而且可以试想setup/teardown发法的一类function。(后面我会详细说一下fixture)
- Helpful assertion message:pytest 可以用python的 assert来检查测试结果
- More than 500 plugins: allure-pytest-2.5.4 , pytest-xdist , pytest-ordering 这三个是我在测试中用到的插件,他们分别帮我实现产生allure报告,同时启动多个浏览器跑测试,给testcase的执行顺序排序。
Powserful fixtures
fixtures as function arguments: 调用一个fixture只需要把fixture的作为参数名放到测试函数中。如
1
2
3
4
5
6
7
8
9
10import pytest
def get_driver():
options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")
driver = webdriver.Chrome(executable_path=CHROME_DRIVER,options=options)
return driver
def test_get_driver(get_driver):
driver = get_driver
assert driver==CHROME_DRIVER, 'driver is not got'Scope: run once per function, per module, per session: Possible values for scope are: function, class, module, package or session,’Within a function request for features, fixture of higher-scopes (such as session) are instantiated first than lower-scoped fixtures (such as function or class). The relative order of fixtures of same scope follows the declared order in the test function and honours dependencies between fixtures.’
1
2
3
4
5
6
7
8
9
def demo1()
print('demo1')
@pytest.fixture(scope='class')
def demo2()
print('demo2')
@pytest.fixture(scope='function')
def demo3()
print('demo3')Parameterizing test: 对于很多测试来说如UI的页面,我们可能需要同时测试到不同search value下的页面,这个时候parametering就会非常好用。如下面的例子。
1
2
3
4
5
6
params=["pytest", "selenium"])
def search_page(request):
search_value=request.param
yield search_page
print("finalizing {}".format(search_value)Modularity: fixtures can use fixtures: fixture也可以用其它fixture就像test function用fixture一样,这样会帮助我们实现代码的模块化 如:
1
2
3
4
5
6
7
8
9
10
11
def get_driver():
driver='Chrome'
return driver
params=["pytest", "selenium"])
def search_page(get_driver, request):
search_driver=get_driver
search_value=request.param
yield search_page
print("finalizing {}".format(search_value)Powserful conftest.py:当有的fixture可以被很多test function运用的时候可以把该fixture放到一个叫‘conftest.py’的文件里面,这样的话你不需要import就可以直接调用里面的fixture。同时你可以有多个conftest.py在不同的子目录中。
allure-pytest
接下来我想聊一聊测试报告的事。在我第一次写python脚本的时候我用的是unittest+html testrunner,当时就觉得生成的报告很清晰,只需要人为的用‘print’就可以在报告里面看到一些case的细节。但是在做UI自动化的时候,我觉得那样的报告并不是很适合,因为UI很多适合需要有截图来向测试人员展示出错的地方。而且,UI测试往往是由很多个步骤组成的,这时候一个‘self-documented’报告就显得特别适合。Allure的report就是这样一个报告。allure的主要优点在于:
- @allure.step: The first and probably most important aspect of the Allure report is that it allows to get a very detailed step-by-step representation of every test invocation. This is made possible with @allure.step decorator that adds invocation of the annotated method or function with provided arguments to the report.
- allure.attach:Reports can display many different types of provided attachments that can complement a test, step or fixture result. Attachments can be created either with invocation of allure.attach(body, name, attachment_type, extension)
- allure.story, allure.feature
好的我的第一篇文章写完了,虽然有一些乱,但是希望能对看到的人有帮助,也希望我以后能多进步。同时我还写了一个demo,感兴趣的人可以看看 https://github.com/LillianZhou/Selenium_Test
参考资料:
[1] https://docs.pytest.org/en/latest/contents.html#toc
[2] https://docs.qameta.io/allure/#_pytest