Selenium自动化测试-unittest单元测试框架使用
来源:互联网 发布:js实现下拉加载更多 编辑:程序博客网 时间:2024/04/27 16:25
一、什么是unittest
这里我们将要用的unittest是python的单元测试框架,它的官网是
https://docs.python.org/2/library/unittest.html,在这里我们可以得到全面的信息。
当我们写的用例越来越多时,我们就需要考虑用例编写的规范与组织,以便于后期的维护,而unittest正是这样一款工具。我们这里用一个示例来展示用unittest脚本是什么样子的。借助Selenium IDE的录制功能,可以完成这样的操作。录制完成后,我们按照如下步骤,将其导出。
然后执行导出的py文件,可以得到类似下面的信息:
---------------------------------------------------Ran 1 test in 12.801sOK
我们打开导出的脚本看一看,录制的是在百度里面搜索关键字Selenium2:
# -*- coding: utf-8 -*-from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support.ui import Selectfrom selenium.common.exceptions import NoSuchElementExceptionfrom selenium.common.exceptions import NoAlertPresentException#导入unittest包import unittest, time, re#SearchTest类继承自unittest.TestCase,表明这是一个测试案例class SearchTest(unittest.TestCase): #setUp用于初始化工作 def setUp(self): self.driver = webdriver.Firefox() self.driver.implicitly_wait(30) self.base_url = "https://www.baidu.com/" self.verificationErrors = [] self.accept_next_alert = True #以test开头的是我们的测试脚本 def test_search(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").click() driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_keys("selenium2") driver.find_element_by_id("su").click() def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException as e: return False return True def is_alert_present(self): try: self.driver.switch_to_alert() except NoAlertPresentException as e: return False return True def close_alert_and_get_its_text(self): try: alert = self.driver.switch_to_alert() alert_text = alert.text if self.accept_next_alert: alert.accept() else: alert.dismiss() return alert_text finally: self.accept_next_alert = True #在每个测试方法后执行,完成清理工作 def tearDown(self): self.driver.quit() self.assertEqual([], self.verificationErrors)#整个测试过程集中在unittest的main()模块中,其默认执行以test开头的方法if __name__ == "__main__": unittest.main()
通过这个我们大概对unittest有个直观的了解了。unittest.main():使用它可以将一个单元测试模块变为可直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中以“test”命名开头的测试方法,并自动执行。执行方法的默认顺序是:根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以以A开头的测试用例方法会优先执行,以a开头会后执行。
二、unittest中的概念
TestCase:
一个Testcase的实例就是一个测试用例,测试用例就是一个完整的测试流程,包括初始化setUp、运行run、测试后的还原tearDown。unittest.TestCase类,所有测试用例类继承的基本类。此类提供了很多assert方法用于检查比较,部分如下:
多数方法都可以见其名知其意,使用的门槛很低。
TestSuite:
对一个功能的测试往往需要多测试用例的,可以把多的测试用例集合在一起执行,这就是TestSuite的概念。常用addTest()方法将一个测试用例添加到测试套件中。
TextTestRunner:
是用来执行测试用例的,其中的run(test)用来执行TestSuite/TestCase。测试的结果会保存在TextTestResult实例中。
TestFixture:
测试准备前要做的工作和测试执行完后要做的工作.包括setUp()和tearDown()。通过覆盖TestCase的setUp和tearDown来实现。
知道了这几个主要的概念,我们就可以把上面的脚本中的最后一行unittest.main()
,改为以下代码:
#构造测试套件 suite = unittest.TestSuite() suite.addTest(SearchTest("test_search")) #执行测试 runner = unittest.TextTestRunner() runner.run(suite)
执行之后发现和之前用unittest.main()的结果一样。
三、用例组织
这里我们假设,脚本当中有多个TestCase如test_case1,test_case2…,那我们应该怎样去控制它们的执行顺序呢?
执行测试用例方案一:
直接用unittest.main()
执行,这里它搜索所有以test开头的测试用例方法,按照ASCII的顺序执行多个用例。
执行测试用例方案二:
先实例化测试套件,将用例加载进去,再用TextTestRunner去执行用例:
suite=unittest.TestSuite() suite.addTest(Test('test_case2')) suite.addTest(Test('test_case1')) runner=unittest.TextTestRunner() runner.run(suite)
执行的顺序是用例的加载顺序,比如这里是先执行2后执行1。
执行测试用例方案三:
在方案2中,如果我们有成百上千个用例的话,一个一个add进去,是不太现实的,那么我们可以用defaultTestLoader来加载:
test_dir = './' discover = unittest.defaultTestLoader.discover(test_dir, pattern='*test.py') runner = unittest.TextTestRunner() runner.run(discover)
这里用./指定了当前目录,指定了*test.py文件,对其当中的用例进行执行,顺序和方案一相同。
如果这里指定的目录下面有多个经pattern匹配上的.py文件呢?调用discover方法,首先通过test_dir定义查找目录,如果文件名满足定义的pattern,那么我们要用for循环来找出所有被筛选出来的用例,并将其循环加到套件中,主要代码如下:
for test_suite in discover: for test_case in test_suite: test_unit.addTests(test_case)
由上面组织用例的方式我们可以知道,在实际的测试用脚本开发中,我们可以在目录下创建xx.py的文件,当用例稳定运行后,可以修改成test_xx.py,以便于添加到测试套件中。注意,文件名的匹配规则,我们可以随便由pattern参数定义。
如果要执行多级目录结构的用例呢?要想被discover读取执行,我们要在目录下加_ init _.py文件
四、一个例子
下面简单的介绍一个用unittest组织的用例结构,先建立D:\Test_Project目录,下面放上test_case和test_report来分别存放用例和报告。
1. 编写测试用例
在test_case下面编写用例,如下简单的示范了在百度上搜索关键字和点击设置的操作:
文件名为:test_baidu.py# -*- coding: utf-8 -*-from selenium import webdriverimport unittest, time, reclass MyTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Firefox() self.driver.implicitly_wait(30) self.base_url = "https://www.baidu.com" self.accept_next_alert = True def test_02baidu_search(self): u''' 测试百度搜索''' driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").click() driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_keys("selenium-test") driver.find_element_by_id("su").click() print("test_baidu__test_02baidu_search") def test_01baidu_setting(self): u''' 测试百度首页设置 ''' driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_css_selector("div#u1 a.pf").click() driver.find_element_by_class_name("setpref").click() driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click() driver.switch_to_alert().accept() print("test_baidu__test_01baidu_setting") def tearDown(self): self.driver.close()#从all_test中调用时,可以不要这个if __name__ == "__main__": unittest.main()
为了显示出组织测试用例的效果,我们将此文件再复制一份,把文件名和方法名等修改一下:
文件名为:test_baidu2.py# -*- coding: utf-8 -*-from selenium import webdriverimport unittest, time, reclass MyTest(unittest.TestCase): u''' 测试baidu的第二个用例''' def setUp(self): self.driver = webdriver.Firefox() self.driver.implicitly_wait(30) self.base_url = "https://www.baidu.com" self.accept_next_alert = True def test_02baidu_search(self): u''' 测试baidu的第二个用例的test_02baidu_search''' driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").click() driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_keys("selenium-test") driver.find_element_by_id("su").click() print("test_baidu2__test_02baidu_search") def test_01baidu_setting(self): u''' 测试baidu的第二个用例的test_01baidu_setting''' driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_css_selector("div#u1 a.pf").click() driver.find_element_by_class_name("setpref").click() driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click() driver.switch_to_alert().accept() print("test_baidu2__test_01baidu_setting") def tearDown(self): self.driver.close()if __name__ == "__main__": unittest.main()
~
2. 美化报告样式和发送结果邮件
上面我们写了 两个测试用例作为示例,我们也可以添加更多的进去。接着我们使用HTMLTestRunner这个开源模块来美化测试报告,关于它的下载使用可以参考https://pypi.python.org/pypi/HTMLTestRunner。然后,我们可以在代码中写上运行完成之后自动发送测试邮件出来,便于我们查看。请参看以下代码:
#coding=utf-8import unittestimport smtplibfrom email.mime.text import MIMETextfrom email.header import Headerimport timeimport HTMLTestRunnerfrom email.mime.application import MIMEApplication#---发送邮件---def send_email(report_file): sender = "XXXXXX@qq.com" receiver = "XXXXXX@qq.com" smtpserver = "smtp.qq.com" #发送邮箱的账号密码,此处使用的是qq邮箱和第三方登录的授权码 username = "XXXXXX@qq.com" password = "gfomcomojtuudijc" #定义邮件正文 file = open(report_file,"rb") mail_body = file.read() file.close() msg = MIMEText(mail_body, _subtype="html", _charset="utf-8") msg["Subject"] = u"自动化测试报告" smtp = smtplib.SMTP_SSL("smtp.qq.com") smtp.login(username, password) smtp.sendmail(sender, receiver, msg.as_string()) smtp.quit() print("Email has send out !")#---将用例添加到测试套件---def creatsuite(): testunit=unittest.TestSuite() test_dir = "D:\\Test_Project\\test_case" discover = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py", top_level_dir = None) for test_suite in discover: for test_case in test_suite: testunit.addTest(test_case) print (testunit) return testunitif __name__ == "__main__": current_time = time.strftime("%Y-%m-%d-%H-%M") report_dir = "D:\\Test_Project\\test_report\\" report_file = report_dir + current_time + "-Test_Result.html" report_stream = open(report_file, "wb") # runner = unittest.TextTestRunner() # 注意HTMLTestRunner只支持python2 runner = HTMLTestRunner.HTMLTestRunner(stream=report_stream,title=u"自动化测试报告", description=u"用例执行情况如下:") runner.run(creatsuite()) report_stream.close() send_email(report_file)
在上面的代码中我们使用了runner = HTMLTestRunner.HTMLTestRunner()
方法来代替runner = unittest.TextTestRunner()
,是为了使用HTMLTestRunner这个模块来美化和输出美观的报告。然后调用方法来发送邮件。运行此文件后,可以得到以下输出的报告:
可以看见使用这个可以清晰的看到用例的执行情况,也便于查看失败用例的原因去调试它。
同时,在我们输入的收件箱里也会受到一份通知邮件,我们可以将此输出报告添加到邮件的正文或附件中,以便于查看。
- Selenium自动化测试-unittest单元测试框架使用
- selenium自动化测试中unittest断言的使用
- unittest 单元测试框架 web测试
- 使用unittest测试框架来写selenium的TestCase
- Python Unittest 自动化单元测试框架Demo
- Python Unittest 自动化单元测试框架Demo
- Python Unittest 自动化单元测试框架Demo
- selenium-python-unittest自动化测试框架(数据和代码完全分离)
- Python+Unittest+自动化:使用Python进行单元测试
- Selenium自动化测试框架
- selenium unittest 单元测试
- Python单元测试框架unittest测试过程简介
- Python的unittest自动化测试框架
- Python UnitTest 框架执行功能自动化测试
- python自动化测试unittest+selenium+HTMLTestRunner(一)
- python自动化测试unittest+selenium+HTMLTestRunner(二)
- Selenium Python自动化测试学习知识积累-unittest
- python单元测试之unittest框架使用总结
- wayland 简介
- 2017 计蒜之道 初赛 第三场 A. 腾讯课堂的物理实验
- ELK
- cocos2dx
- MYSQL性能优化之Mysql数据库索引优化
- Selenium自动化测试-unittest单元测试框架使用
- Struts2(二)使用Struts2访问ServletAPI对象
- 多进程、多线程以及如何选择?
- 剑指offer——复杂链表的复制(还不错,空间优先法和时间优先法)
- 大话设计模式阅读笔记-抽象工厂模式
- 如何控制表单内tab键切换的顺序
- 6月19号——C
- Struts2(三)使用Struts2实现文件的上传和下载
- 扩展欧几里得算法