79节
目录
1.pytest 筛选用例
2.pytest的断言 assert
3.测试报告
4.pytest用例执行顺序
5.数据驱动
1.pytest 筛选用例:标记功能
1).标签打在整个测试类上面
举例,在上面的登录测试用例的测试类上面加标签:@pytest.mark.login
①在pytest.ini文件中加上标签名:login
②在TestLogin类上面加@pytest.mark.login
③terminal中运行 pytest -m "login"
代码实现:
"""登录功能的测试用例""" import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登录功能的测试类""" @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空 driver.find_element_by_name("password").send_keys("")#定位输入的密码为空 driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #断言 self.assertTrue(actual_result == "请输入手机号") # @pytest.mark.success def test_login_success(self): """登录成功测试用例 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待时间 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] driver.implicitly_wait(wait_time) #2.访问登录页面 url="http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("15*********") driver.find_element_by_name("password").send_keys("15") driver.find_element_by_class_name("btn-special").click() #4.获取实际结果,进行断言 actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text print(type(actual_result)) self.assertTrue("我的帐户[小蜜蜂177872141]" in actual_result)
运行结果:
2).标记功能组合------不同的testcase的py文件中,可以同时运行多个
语法1.:
pytest -m "register_error or success" -------只需要满足一个条件就可以运行(可以组合2个或者2个以上)
pytest -m "register_error and success" -------2个条件同事满足才可以运行(可以组合2个或者2个以上)
pytest -m "register_error and not success" -------2个条件同事满足才可以运行(可以组合2个或者2个以上),取非
举例:运行test_register.py中的register_error,或者test_login中的success
首先别忘记在ini文件中注册tagname
代码实现:
test_register.py:
import unittest import pytest class TestRegister(unittest.TestCase): """注册功能的测试类""" @pytest.mark.register_error def test_register_error(self): pass
test_login.py:
"""登录功能的测试用例""" import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登录功能的测试类""" @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空 driver.find_element_by_name("password").send_keys("")#定位输入的密码为空 driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #断言 self.assertTrue(actual_result == "请输入手机号")
运行pytest -m "register_error or success",结果:
3)标记功能组合---------一个函数或者类上面,可以加多个标签
例1: 标签组合and
代码如下:
"""登录功能的测试用例""" import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登录功能的测试类"""
@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver 。 。 。 。
运行:pytest -m "login and smoke" ,类标签有2个方法,但是and smoke,表示只筛选类里面的标记为smoke的方法。、
结果:
例2: 标签组合 not
运行TestLogin这个类下面的success的方法(success方法没有打标签)
运行:pytest -m "login and not smoke"
或者pytest -m "login and not error"
import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time @pytest.mark.login class TestLogin(unittest.TestCase): """登录功能的测试类"""
@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空 driver.find_element_by_name("password").send_keys("")#定位输入的密码为空 driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #断言 self.assertTrue(actual_result == "请输入手机号") def test_login_success(self): """登录成功测试用例 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待时间 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] driver.implicitly_wait(wait_time) #2.访问登录页面 url="http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("15********") driver.find_element_by_name("password").send_keys("15") driver.find_element_by_class_name("btn-special").click() #4.获取实际结果,进行断言 actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text print(type(actual_result)) self.assertTrue("我的帐户[小蜜蜂177872141]" in actual_result)
注意:用例标记的时候,标签如果有逻辑运算,一定要加双引号。
2.pytest的断言 assert
背景:上篇博客中有提到,pytest是可以脱离类存在的,所以单个函数的断言,是用不了self.assertTrue
1).pytest 的断言直接用assert即可
assert 3>2、assert 4=4 这样表述即可。
3.测试报告
1).安装HTML的测试报告 pip install pytest-html
2).运行结果生成报告:pytest -m "login and not error" --html=report.html
即可在项目下生成测试报告。
3).测试报告生成时间戳:脚本运行pytest
①在run.py文件中,以pytest.main()形式运行用例。
首先看下main()方法的源码:参数表示:列表形式的命令行参数;插件暂时用不到,先不看
run.py如下:
"运行测试用例" import pytest if __name__ == '__main__': pytest.main(["--html=report1.html"])
下面将测试报告加上时间戳:
①import datatime
②ts = datatime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
run.py实现:
"运行测试用例" import pytest import datetime ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") if __name__ == '__main__': pytest.main(["--html={}report.html".format(ts)])
4.pytest用例执行顺序
类里面的用例方法:从上到下,运行(简单来说,想让哪个用例先运行,就把用例写在前面)
5.数据驱动 79节45min
首先,回顾下,如果用unittest框架去测试,代码如下:
"""登录功能的测试用例""" import ddt import unittest import pytest from middware.handler import HandlerMiddle from config.config import Wait_time data = HandlerMiddle.excel.read_data("login") @ddt.ddt class TestLogin(unittest.TestCase): """登录功能的测试类""" @ddt.data(*data) def test_login_error(self,test_info): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"]) driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"]) driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text expected_result = test_info["expected_result"] #断言 self.assertTrue(actual_result == expected_result)
通过pytest用例筛选运行error用例,读取web_excel.xlsx中的2条用例(一条通过,一条不通过),run,py代码如下:
"运行测试用例" import pytest import datetime ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") if __name__ == '__main__': pytest.main(["--html={}report.html".format(ts), "-m error"])
用unittest框架(使用筛选用例)的数据驱动,运行通过。
下面用pytest的数据驱动完成测试:
pytest数据驱动的语法:
① 在用例的方法上添加:@pytest.mark.parametrize("test_info",data) data表示 列表表示的数据
② 用例方法中添加参数test_info
注:pytest中,类上面不需要加任何东西(因为它可能没有类)
pytest中,parametrize中的第一个参数“test_info” 跟函数中的参数名称必须是一致的------->(def test_login_error(self,test_info):)
完成上面的操作后,还有需要跟unittest区分的是:不能继承unittest.TestCase,断言就不能用self.assertTrue了
代码实现如下:
"""登录功能的测试用例""" import pytest from middware.handler import HandlerMiddle from config.config import Wait_time data = HandlerMiddle.excel.read_data("login") @pytest.mark.login class TestLogin(): """登录功能的测试类""" @pytest.mark.smoke @pytest.mark.error @pytest.mark.parametrize("test_info",data) def test_login_error(self,test_info): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"]) #定位输入手机号为空 driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"])#定位输入的密码为空 driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text expected_result = test_info["expected_result"]
#断言 assert actual_result == expected_result
运行上面的run.py,测试通过。
数据驱动注意事项:
①在使用@pytest.mark.parametrize("test_info",data)做数据驱动时,pytest和unittest不兼容,即,如果想使用pytest的数据驱动,就不能继承unittest.TestCase,并修改断言
②如果用unittest写用例,就需要用 unittest 的数据驱动。(类 继承unittest.TestCase;添加ddt)
总结来说:pytest不跟unittest兼容的是:数据驱动parametrize,测试夹具fixture,hook
只要用上面的三个,pytest和unittest 就是不兼容。