# !/usr/bin/env python # -*- coding:utf-8 -*- import pytest ‘‘‘ 在单元测试的组件中,主要分为测试?例,测试固件,测试套件,测试执?以及测试报告 装饰器@pytest.fixture(),它是声明?个函数是fixture 如果测试函数的参数列表中包含了fixture,pytest执?时会检测到,并且在测试函数运?前执?该fixture fixture可以完成任务,也可以返回数给测试函数 ‘‘‘ @pytest.fixture() def login(username=‘admin‘, password=‘admin‘): if username == ‘admin‘ and password == ‘admin‘: return True # 返回值 else: print(‘账户或密码错误‘) def test_profile(login): # 测试函数test_profile的形式参数是login,同时该形式参数是fixture函数对象 assert login == True from selenium import webdriver @pytest.fixture() def driver(): return webdriver.Chrome() def test_baidu_title(driver): driver.get(‘https://www.baidu.com‘) assert driver.title == ‘百度一下,你就知道‘ if __name__ == ‘__main__‘: pytest.main(["-v", "-s", "test_fixture.py"])
# !/usr/bin/env python # -*- coding:utf-8 -*- from selenium import webdriver ‘‘‘ selenium在Python中是插件需要导入 如果导入这个库,在执行时不需要--driver Chrome 没有导入selenium,就需要加上--driver Chrome ‘‘‘ import pytest import time as t @pytest.fixture() def driver(): return webdriver.Chrome() @pytest.fixture() def init(driver): # UI自动化固件测试 driver.maximize_window() driver.get(‘https://www.baidu.com‘) yield # 测试步骤和断言 driver.close() def test_baidu_title(driver): assert driver.title == ‘百度一下,你就知道‘ def test_baidu_so(driver): so = driver.find_element_by_id(‘kw‘) so.send_keys(‘admin‘) t.sleep(3) assert so.get_attribute(‘value‘) == ‘admin‘ ‘‘‘ class TestBaidu(object): @pytest.fixture() def driver(self): return webdriver.Chrome() @pytest.fixture() def init(self, driver): # UI自动化固件测试 driver.maximize_window() driver.get(‘https://www.baidu.com‘) yield # 测试步骤和断言 driver.close() def test_baidu_title(self, init, driver): assert driver.title == ‘百度一下,你就知道‘ def test_baidu_so(self, init, driver): so = driver.find_element_by_id(‘kw‘) so.send_keys(‘admin‘) t.sleep(3) assert so.get_attribute(‘value‘) == ‘admin‘ ‘‘‘ if __name__ == ‘__main__‘: pytest.main(["-v", "-s", "test_fixture_init.py"])
# !/usr/bin/env python # -*- coding:utf-8 -*- import pytest import time as t @pytest.fixture() def init(selenium): # 自动化固件测试,打浏览器对应网页 selenium.maximize_window() selenium.get(‘https://www.baidu.com‘) yield # 测试步骤和断言 selenium.close() def test_baidu_title(selenium): assert selenium.title == ‘百度一下,你就知道‘ def test_baidu_so(selenium): so = selenium.find_element_by_id(‘kw‘) so.send_keys(‘admin‘) t.sleep(3) assert so.get_attribute(‘value‘) == ‘admin‘ if __name__ == ‘__main__‘: pytest.main(["-v", "-s", "--driver","Chrome","test_fixture_init.py"])
# !/usr/bin/env python # -*- coding:utf-8 -*- import pytest from selenium import webdriver @pytest.fixture() def driver(): return webdriver.Chrome() @pytest.fixture() def init(driver): driver.maximize_window() driver.get(‘https://file.qq.com/‘) yield driver.close() ‘‘‘ 通过conftest.py可以共享fixture,可以解决测试固件的案例应?,依据它可编写多个案例 conftest.py是?个Python模块的?件,但是它是无法导?,必须在对应工程根目录下 在Conftest.py?件中主要使?scope的参数来控制fixture执?配置和销毁逻辑 Session:会话级别:针对?个项?中所有的模块,类,以及测试函数 Module:模块级别,主要是针对?个模块的范围 Class:针对类级别,主要是针对?个类的范围 Function:函数级别,主要是针对?个函数的 ‘‘‘
#! /usr/bin/env pytho # -*- coding:utf-8 -*- import pytest import time as t def test_file_qq_001(init, driver): ‘‘‘登录验证:校验点击注册跳转到注册的页面‘‘‘ t.sleep(2) driver.switch_to.frame(‘login_frame1‘) driver.switch_to.frame(‘ptlogin_iframe‘) nowHandler = driver.current_window_handle driver.find_element_by_link_text(‘注册新帐号‘).click() allHandlers = driver.window_handles for handler in allHandlers: if nowHandler != handler: driver.switch_to.window(handler) t.sleep(2) assert driver.title == ‘QQ注册‘ def test_file_qq_002(init, driver): t.sleep(3) driver.switch_to.frame(‘login_frame1‘) driver.switch_to.frame(‘ptlogin_iframe‘) driver.find_element_by_link_text(‘帐号密码登录‘).click() t.sleep(1) username = driver.find_element_by_xpath(‘//*[@id="uin_tips"]‘) assert username.text == ‘支持QQ号/邮箱/手机号登录‘ if __name__ == ‘__main__‘: pytest.main(["-v", "-s", "test_qq_file.py"])
除conftest.py,还可以使用pytest.ini,它是Pytest测试框架的主配置文件可以改变Pytest默认行为
[pytest] #指定执行时候的默认信息 addopts = -v -s #注册标记 markers = login:执行标记为login的测试函数 register:执行标记为register的测试函数 logout:执行标记为logout的测试函数 #指定Pytest的最低版本号 minversion = 3.0 #指定忽略执行的目录 norecursedirs = .pytest_cache #指定测试目录 testpaths = tests #指定测试模块搜索的规则 python_files = test_* #指定测试类搜索的规则 python_classes = Test* #指定测试函数搜索规则 python_functions = test_* ;配置文件编码为GBK;与操作系统编码一致
Pytest-sugar 在执?的时候显示进度条,即使有失败的也会?刻显示
安装命令:ip3 install pytest-sugar
Pytest-html 在执?后?成给予html的测试报告,会在当前?录下?成 ?个report.html的?件
安装它的命令为:pip3 install pytest-html
命令:pytest -v -s --html=report.html 在当前目录下生成一个测试用例
python -m pytest tests/ --html=report/index.html 会生成一个测试报告放在report下
Pytest-rerunfailures 对执?失败的再次执?
安装的命令为:pip3 install pytest-rerunfailures
--reruns --N N就是重试的次数
pytest -v -s --reruns N --html=report.html
Allure测试报告
安装库:pip3 install allure-pytest
第一种使用方法
(1)在命令控制台进入工程,输入:
(2)python -m pytest tests --alluredir=report/result ——> result下生成json的文件
(3)python -m pytest tests --alluredir=report/result ——> report下生成html的目录和html的测试报告
(4)allure serve report/result ——> 启动allure的服务,打开测试报告
第二种使用方法
在代码中以主函数形式调用
# !/usr/bin/env python # -*- coding:utf-8 -*- import pytest import subprocess def add(a, b): return a + b def test_add_001(): assert add(1, 2) == 2 def test_add_002(): assert add(‘h‘, ‘i‘) == ‘hi‘ def test_add_003(): assert 2 == 3 def add_004(): assert 2 == 3 class TestLogin(object): def test_login_001(self): pass def test_login_002(self): pass # if __name__ == ‘__main__‘: # pytest.main(["-v", "-s", "test_add.py::TestLogin::test_login_002"]) if __name__ == ‘__main__‘: pytest.main(["-s", "-v", "test_add.py", "--alluredir", "./report/result"]) subprocess.call(‘allure generate report/result/ -o report/html --clean‘, shell=True) subprocess.call(‘allure open -h 127.0.0.1 -p 8088 ./report/html‘, shell=True)
在python的单元测试框架unittest中,使?到的覆盖率?具是coverage
它属于第三?的库,安装的命令为:pip3 install coverage