一、继承
继承能解决什么问题?
unittest每个模块都要用到前提条件以及清理,如果有上百个模块,我们要改域名和浏览器,就会工作量很大特别麻烦,这时我们可以用继承的思想只用改一次
我们可以将前提和清理提出来单独放到一个文件里,具体代码如下
from selenium import webdriver
import unittestclass Init(unittest.TestCase):@classmethoddef setUpClass(cls) -> None:cls.driver=webdriver.Chrome()cls.driver.maximize_window()cls.driver.get('http://www.baidu.com')cls.driver.implicitly_wait(30)@classmethoddef tearDownClass(cls) -> None:cls.driver.quit()
然后我们写测试用例的时候可以继承它,具体代码如下
from selenium import webdriver
import unittestfrom 单元测试框架.test.init import Init
class BaiduTest(Init):def test_baidu_title(self):'''百度测试:验证百度首页的title'''# assert self.driver.title=='百度一下,你就知道'self.assertEqual(self.driver.title,'百度一下,你就知道')def test_baidu_url(self):'''百度测试:验证百度首页的url'''assert self.driver.current_url=='https://www.baidu.com/'def test_baidu_video(self):'''百度测试:验证点击视频后跳转到视频的页面'''nowhandler=self.driver.current_window_handleself.driver.find_element_by_link_text('视频').click()allhandlers=self.driver.window_handlesfor handler in allhandlers:if handler!=nowhandler:self.driver.switch_to.window(handler)self.assertTrue(self.driver.current_url,'https://haokan.baidu.com/?sfrom=baidu-top')self.driver.close()self.driver.switch_to.window(nowhandler)def test_baidu_map(self):'''百度测试:验证点击地图后跳转到地图的页面'''nowhandler=self.driver.current_window_handleself.driver.find_element_by_link_text('地图').click()allhandlers=self.driver.window_handlesfor handler in allhandlers:if handler!=nowhandler:self.driver.switch_to.window(handler)self.assertTrue(self.driver.current_url.startswith('https://map.baidu'))self.driver.close()self.driver.switch_to.window(nowhandler)if __name__ == '__main__':unittest.main()
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036
二、参数化
在unittest测试框架中,参数化使用的库为:parameterized 安装方式为:pip3 install parameterized
参数化:
我们把相同的测试步骤,应用于不同的测试场景,那么我们就可以使用参数化了
可以解决的问题是可以使用少量的测试代码,来覆盖更多的测试场景
例如:我们测一下sina邮箱的登录模块,代码如下:
from selenium import webdriver
import unittest
import time as t
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()def test_sina_null(self):'''sina邮箱验证:登录账户为空'''self.driver.find_element_by_class_name('loginBtn').click()divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'请输入邮箱名')def test_sina_email_format(self):'''sina邮箱验证:登录邮箱格式不正确'''self.driver.find_element_by_id('freename').send_keys('qwert')self.driver.find_element_by_class_name('loginBtn').click()divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'您输入的邮箱名格式不正确')def test_sina_username_error(self):'''sina邮箱验证:登录账户不匹配'''self.driver.find_element_by_id('freename').send_keys('asdf@sina.com')self.driver.find_element_by_id('freepassword').send_keys('asdfg')self.driver.find_element_by_class_name('loginBtn').click()t.sleep(3)divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,'登录名或密码错误')if __name__ == '__main__':unittest.main()
由于登录模块主要是⽤户名和密码的input表单的验证以及错误信息的验证,我们可以把用户名、密码、错误信息的验证参数化,具体实现的代码如下:
from selenium import webdriver
import unittest
import time as t
from parameterized import parameterized,param
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()@parameterized.expand([param('','','请输入邮箱名'),param('wertasd', 'asdf', '您输入的邮箱名格式不正确'),param('wertasd@sina.cn', 'asdf', '登录名或密码错误')])def test_sina_login(self,username,password,result):self.driver.find_element_by_id('freename').send_keys(username)t.sleep(3)self.driver.find_element_by_id('freepassword').send_keys(password)t.sleep(3)self.driver.find_element_by_class_name('loginBtn').click()t.sleep(3)divText=self.driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')self.assertEqual(divText.text,result)
三、断言
assertEqual
assertEqual()是验证两个值相等,值的是数据类型与内容也是相等的,⻅案例代码:
from selenium import webdriver
import unittest
class BaiduTest(unittest.TestCase):def setUp(self) -> None:self.driver=webdriver.Chrome()self.driver.get('http://www.baidu.com')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None:self.driver.quit()def test_baidu_title(self):'''百度测试:验证百度首页的title'''# assert self.driver.title=='百度一下,你就知道'self.assertEqual(self.driver.title,'百度一下,你就知道')
assertTrue
返回的是bool类型,也就是对被测试的对象进⾏验证,如果返回的是boolean类型并且是true,那么结果验证通过,那么⽅法assertFlase()验证的是被测试对象返回的内容是false,⻅案例代码:
from selenium import webdriver
import unittest
import time as t
class BaiduTest(unittest.TestCase):def setUp(self) -> None: #前提self.driver=webdriver.Chrome()self.driver.get('https://mail.sina.com.cn/')self.driver.maximize_window()self.driver.implicitly_wait(30)def tearDown(self) -> None: #清理self.driver.quit()def test_sina_isLogin(self):'''sina邮箱验证,判断自动登录是否勾选'''isLogin=self.driver.find_element_by_id('store1')self.assertTrue(isLogin.is_selected())
assertIn
assertIn()值的是⼀个值是否包含在另外⼀个值⾥⾯,在这⾥特别的强调⼀下,在assertIn()的⽅法⾥⾯,有两个参数,那么值的包含其实就是第⼆个实际参数包含第⼀个实际参数。与之相反的⽅法是assergNotIn(),⻅案例代码:
import unittest
from selenium import webdriver
class UiTest(unittest.TestCase):
def setUp(self) -> None:
self.driver=webdriver.Chrome()
self.driver.maximize_window()
self.driver.get('http://www.baidu.com')
self.driver.implicitly_wait(30)
def tearDown(self) -> None:
self.driver.quit()
def test_baidu_title_001(self):
self.assertIn('百度',self.driver.title)
def test_baidu_title_002(self):
self.assertIn('百度⼀下,你就知道',self.driver.title)
if __name__ == '__main__':
unittest.main()
四、测试报告
在unittest的框架中,⽣成测试报告需要使⽤到HTMLTestRunner
import unittest
import os
from 单元测试框架.HTMLTestRunner import HTMLTestRunner #从HTMLTestRunner模块调用HTMLTestRunner类def getTests():'''加载所有的测试模块'''suite=unittest.TestLoader().discover(#找到被执行模块的路径start_dir=os.path.dirname(__file__),#加载路径下所有以test_开头的测试模块的文件pattern='test_*.py' #正则表达式)return suitedef runSuite():unittest.TextTestRunner().run(getTests())def base_dir():return os.path.dirname(os.path.dirname(__file__))#获取当前目录的上级目录def run():fp=open(os.path.join(base_dir(),'report','report.html'),'wb')#拼接report.html的路径 wb 二进制的方式写入runner=HTMLTestRunner(stream=fp, #流 执行一个写入一个title='UI自动化测试报告',description='' )runner.run(getTests())if __name__ == '__main__':run()
怎么解决每次生成的测试报告不覆盖之前的测试报告,同时被保留:
解决方法:引入时间库获取时间戳
代码如下:
import time
import unittest
import os
from HTMLTestRunner import HTMLTestRunnerdef getTests():'''加载所有的测试模块'''suite=unittest.TestLoader().discover(#找到被执行模块的路径start_dir=os.path.dirname(__file__),#加载路径下所有以test_开头的测试模块的文件pattern='test_*.py' #正则表达式)return suitedef getNowTime():return time.strftime('%y-%m-%d %H-%M-%S',time.localtime(time.time()))def base_dir():return os.path.dirname(os.path.dirname(__file__))def run():fp=open(os.path.join(base_dir(),'report',getNowTime()+'report.html'),'wb')runner=HTMLTestRunner(stream=fp,title='UI自动化测试报告',description='')runner.run(getTests())if __name__ == '__main__':run()
这样每次执行的都会生成一个测试报告:
END今天的分享就到此结束了,点赞关注不迷路~