当前位置:网站首页>[Software testing] unittest framework for automated testing
[Software testing] unittest framework for automated testing
2022-08-05 03:24:00 【Money, Kun】
1.什么是unittest框架
unittest 是python 的单元测试框架,它主要有以下作用:
- 提供用例组织与执行
当你的测试用例只有几条时,可以不必考虑用例的组织,但是,当测试用例达到成百上千条时,大量的测试用例堆砌在一起,就产生了扩展性与维护性等问题,此时需要考虑用例的规范与组织问题了.单元测试框架就是来解决这个问题的. - 提供丰富的比较方法
在用例执行完之后都需要将实际结果与预期结果进行比较(断言),从而断定用例是否可以顺利通过.单元测试一般会提供丰富的断言方法.例如,判断相等/不相等、包含/不包含、True/False等断言方法. - 提供丰富的日志
当测试用例执行失败时能抛出清晰的失败原因,当所有用例执行完成后能提供丰富的执行结果.例如,总的执行时间,失败用例数,成功用例数等
2.unittest的简单使用
下面为unittest框架的脚本:
import unittest
from selenium import webdriver
import time
# 定义一个类继承unittest.TestCase
class Baidu1(unittest.TestCase):
# 测试固件
# 环境的初始化
def setUp(self):
print("--setUp--")
# self 定义的是全局变量,Otherwise it can only be used inside this method
self.driver = webdriver.Chrome()
# 访问的URL
self.url = "https://www.baidu.com"
self.driver.maximize_window()
time.sleep(3)
# Restoration of the test environment
def tearDown(self):
print("--tearDown--")
self.driver.quit()
# 测试用例 必须以test_开头 否则不识别,The execution order of test cases is in ascending lexicographical order of test methods
def test_t1(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_link_text("hao123").click()
driver.implicitly_wait(3)
print(driver.title)
time.sleep(3)
# 注解:忽略测试用例的执行
@unittest.skip("skipping")
def test_t2(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_id("kw").send_keys("胡歌")
driver.find_element_by_id("su").submit()
time.sleep(3)
print(driver.title)
time.sleep(3)
def test_t3(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_id("kw").send_keys("刘浩存")
driver.find_element_by_id("su").submit()
print(driver.title)
time.sleep(3)
# 主方法 Test method execution entry
if __name__ == "__main__":
unittest.main()
创建步骤
1.定义一个类继承unittest.TestCase;
2.Initialize the test firmware;
setUp() 和 setDown() 是unittest框架中的测试固件
3.编写测试用例
The methods of the test cases are the same test_ 开头,以test_开头命名的方法,是测试方法,在运行整个类的时候会默认执行;
4.编写主方法
unittest提供了全局的main()方法,使用它可以方便地将一个单元测试模块变成可以直接运行的测试脚本.main()方法搜索所有包含在该模块中以”test"命名的测试方法,并自动执行他们.
3.Execute test scripts in batches
in the above test test script,We define three test cases,We can execute multiple test cases sequentially,When we write multiple tests in multiple classes for different functions in our actual development environment, how can we execute all the test scripts at once,Testing is needed测试套件,A test suite can execute test cases from multiple classes in batches,下面演示使用:
- Define two test classes
测试1
import unittest
from selenium import webdriver
import time
# 定义一个类继承unittest.TestCase
class Baidu1(unittest.TestCase):
# 测试固件
# 环境的初始化
def setUp(self):
print("--setUp--")
# self 定义的是全局变量,Otherwise it can only be used inside this method
self.driver = webdriver.Chrome()
# 访问的URL
self.url = "https://www.baidu.com"
self.driver.maximize_window()
time.sleep(3)
# Restoration of the test environment
def tearDown(self):
print("--tearDown--")
self.driver.quit()
# 测试用例 必须以test_开头 否则不识别,The execution order of test cases is in ascending lexicographical order of test methods
def test_t1(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_link_text("hao123").click()
driver.implicitly_wait(3)
print(driver.title)
time.sleep(3)
# 注解:忽略测试用例的执行
@unittest.skip("skipping")
def test_t2(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_id("kw").send_keys("胡歌")
driver.find_element_by_id("su").submit()
time.sleep(3)
print(driver.title)
time.sleep(3)
def test_t3(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_id("kw").send_keys("刘浩存")
driver.find_element_by_id("su").submit()
print(driver.title)
time.sleep(3)
# 主方法 Test method execution entry
if __name__ == "__main__":
unittest.main()
测试2
import unittest
from selenium import webdriver
import time
# Automated tests for blog browsing
class Baidu2(unittest.TestCase):
# 测试固件
def setUp(self):
print("--setUp--")
self.driver = webdriver.Chrome()
self.url = "https://blog.csdn.net/qq_57549633"
self.driver.maximize_window()
time.sleep(3)
# Restoration of the test environment
def tearDown(self):
print("--tearDown--")
self.driver.quit()
# 测试用例 必须以test_开头 否则不识别
def test_t1(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_xpath("//*[@id='userSkin']/div[2]/div/div[2]/div[1]/div[2]/div/div/div[1]/article/a/div[1]/h4").click()
driver.back()
time.sleep(3)
def test_t2(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_xpath("//*[@id='userSkin']/div[2]/div/div[2]/div[1]/div[2]/div/div/div[7]/article/a/div[1]").click()
driver.back()
time.sleep(3)
print(driver.title)
time.sleep(3)
def test_t3(self):
driver = self.driver
url = self.url
driver.get(url)
driver.find_element_by_xpath("//*[@id='userSkin']/div[2]/div/div[2]/div[1]/div[2]/div/div/div[13]/article/a/div[1]/h4").click()
driver.back()
print(driver.title)
time.sleep(3)
# 主方法
if __name__ == "__main__":
unittest.main()
- addTest()方法
TestSuite类的addTest()方法可以把不同的测试类中的测试方法组装到测试套件中,但是addTest()一次只能把一个类里面的一个测试方法组装到测试套件中.方式如下:
将testbaidu1.py、testbaidu2.py中的测试方法放到一个测试套件中,在testsuite.py中实现.
import unittest
import TestBaidu1
import TestBaidu2
from selenium import webdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com")
# Organizing test suite methods
def creatSuit():
# 1.Put the test methods that need to be executed from the classes of different test scripts in a test suite
suit=unittest.TestSuite()
suit.addTest(TestBaidu1.Baidu1("test_t1"))
suit.addTest(TestBaidu1.Baidu1("test_t2"))
suit.addTest(TestBaidu2.Baidu2("test_t3"))
return suit
# The main method loads the suite
if __name__=="__main__":
suite = creatSuit()
# verbosity 日志显示级别,分为 0 1 2
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
- makeSuite()和TestLoader()的应用
在unittest 框架中提供了makeSuite() 的方法,makeSuite可以实现把测试用例类内所有的测试case组成的测试套件TestSuite ,unittest 调用makeSuite的时候,只需要把测试类名称传入即可.
TestLoader 用于创建类和模块的测试套件,一般的情况下,使TestLoader().loadTestsFromTestCase(TestClass) 来加载测试类.
import unittest
import TestBaidu1
import TestBaidu2
from selenium import webdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com")
# Organizing test suite methods
def creatSuit():
# 2.Add all methods from a class in one test script to the suite
suit=unittest.TestSuite()
suit.addTest(unittest.makeSuite(TestBaidu1.Baidu1))
suit.addTest(unittest.makeSuite(TestBaidu2.Baidu2))
# suite1 = unittest.TestLoader().loadTestsFromTestCase(testbaidu1.Baidu1)
# suite2 = unittest.TestLoader().loadTestsFromTestCase(testbaidu2.Baidu2)
# suite = unittest.TestSuite([suite1, suite2])
return suite
# The main method loads the suite
if __name__=="__main__":
suite = creatSuit()
# verbosity 日志显示级别,分为 0 1 2
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
- discover()的应用
discover 是通过递归的方式到其子目录中从指定的目录开始, 找到所有测试模块并返回一个包含它们对象的TestSuite ,然后进行加载与模式匹配唯一的测试文件,discover 参数分别discover(dir,pattern,top_level_dir=None)
import unittest
import TestBaidu1
import TestBaidu2
from selenium import webdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com")
# Organizing test suite methods
def creatSuit():
# 3.Add test cases for all test scripts in the entire folder to the suite
discover=unittest.defaultTestLoader.discover("../Test", pattern="TestBaidu*.py", top_level_dir=None)
return discover
# The main method loads the suite
if __name__=="__main__":
suite = creatSuit()
# verbosity 日志显示级别,分为 0 1 2
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
用例的执行顺序:unittest 框架默认加载测试用例的顺序是根据ASCII 码的顺序,数字与字母的顺序为: 09,AZ,a~z .
所以, TestAdd 类会优先于TestBdd 类被发现, test_aaa() 方法会优先于test_ccc() 被执行.对于测试
directory and test files, unittest 框架同样是按照这个规则来加载测试用例.
4.unittest断言
自动化的测试中, 对于每个单独的case来说,一个case的执行结果中, 必然会有期望结果与实际结果, 来判断该case是通过还是失败, 在unittest The library provides a number of utility methods to check the expected value against the actual
值, 来验证case的结果.
下面是一些常用的断言:
代码演示:
import time
from selenium import webdriver
import unittest
# 定义一个类继承unittest.TestCase
class Test(unittest.TestCase):
# 测试固件
# 环境的初始化
def setUp(self):
print("--setUp--")
# self 定义的是全局变量,Otherwise it can only be used inside this method
self.driver = webdriver.Chrome()
self.url = "https://www.baidu.com"
self.driver.maximize_window()
time.sleep(3)
# Restoration of the test environment
def tearDown(self):
print("--tearDown--")
self.driver.quit()
# 测试用例
def test_t1(self):
driver=self.driver
url=self.url
driver.get(url)
time.sleep(3)
driver.find_element_by_id("kw").send_keys("胡歌")
driver.find_element_by_id("su").click()
driver.implicitly_wait(5)
print(driver.title)
# self.assertEqual("胡歌_百度搜索", driver.title, msg="Web page not opened")
self.assertTrue("百度一下,你就知道" == driver.title, msg="内容不相等")
time.sleep(5)
driver.quit()
5.HTML报告生成
脚本执行完毕之后,还需要看到HTML报告,下面我们就通过HTMLTestRunner.py 来生成测试报告.
HTMLTestRunner支持python2.7.python3可以参见http://blog.51cto.com/hzqldjb/1590802来进行修改.
HTMLTestRunner.py 文件,下载地址: http://tungwaiyip.info/software/HTMLTestRunner.html
下载后将其放在testcase目录中去或者放入…\Python27\Lib 目录下(windows).
import HTMLTestRunner
import sys
import unittest
from selenium import webdriver
import os
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# A way to organize a test suite
def creatSuit():
# TestAll test cases in the directory
discover=unittest.defaultTestLoader.discover("../Test", pattern="Test*.py", top_level_dir=None)
return discover
if __name__ == "__main__":
# 当前路径、 等同于./
curpath = sys.path[0]
# 取当前时间
now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))
if not os.path.exists(curpath + '/resultreport'):
os.makedirs(curpath + '/resultreport')
# 文件名
filename = curpath + '/resultreport/' + now + 'resultreport.html'
with open(filename, 'wb') as fp:
# 出html报告
runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u'测试报告',description=u'用例执行情况',verbosity=2)
suite = creatSuit()
runner.run(suite)
在resultreportThe test report generated in the directory:
The test report will show the execution of the use case in detail(All my test cases here pass):
5.异常捕捉与错误截图
用例不可能每一次运行都成功,肯定运行时候有不成功的时候.如果可以捕捉到错误,并且把错误截图保存,这将是一个非常棒的功能,也会给我们错误定位带来方便.
import time
import os
from selenium import webdriver
import unittest
# 定义一个类继承unittest.TestCase
class Test(unittest.TestCase):
# 测试固件
# 环境的初始化
def setUp(self):
print("--setUp--")
# self 定义的是全局变量,Otherwise it can only be used inside this method
self.driver = webdriver.Chrome()
self.url = "https://www.baidu.com"
self.driver.maximize_window()
time.sleep(3)
# Restoration of the test environment
def tearDown(self):
print("--tearDown--")
self.driver.quit()
# 测试用例
def test_t1(self):
driver = self.driver
url = self.url
driver.get(url)
time.sleep(3)
driver.find_element_by_id("kw").send_keys("胡歌")
driver.find_element_by_id("su").click()
driver.implicitly_wait(5)
print(driver.title)
try:
self.assertNotEqual(driver.title, "百度一下,你就知道", msg="内容不一致")
except:
self.sasavescreenshot(driver, "except.png")
time.sleep(5)
# Save a screenshot of the error
def savescreenshot(self, driver, file_name):
if not os.path.exists('./image'):
os.makedirs('./image')
now = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))
# 截图保存
driver.get_screenshot_as_file('./image/' + now + '-' + file_name)
time.sleep(3)
# 主方法
if __name__ == "__main__":
unittest.main()
边栏推荐
- 高项 02 信息系统项目管理基础
- 队列题目:最近的请求次数
- 21 Days Learning Challenge (2) Use of Graphical Device Trees
- Principle and Technology of Virtual Memory
- YYGH-13-Customer Service Center
- Native js realizes the effect of selecting and canceling all the multi-select boxes
- Dameng 8 database export and import
- Question about #sql shell#, how to solve it?
- 使用二维码传输文件的小工具 - QFileTrans 1.2.0.1
- 运维监控系统之Open-Falcon
猜你喜欢
论治理与创新,2022 开放原子全球开源峰会 OpenAnolis 分论坛圆满落幕
J9 Digital Currency: What is the creator economy of web3?
Everyone in China said data, you need to focus on core characteristic is what?
你要的七夕文案,已为您整理好!
【 genius_platform software platform development 】 : seventy-six vs the preprocessor definitions written cow force!!!!!!!!!!(in the other groups conding personnel told so cow force configuration to can
Developing Hololens encountered The type or namespace name 'HandMeshVertex' could not be found..
龙蜥社区第二届理事大会圆满召开!理事换届选举、4 位特约顾问加入
In 2022, you still can't "low code"?Data science can also play with Low-Code!
presto启动成功后出现2022-08-04T17:50:58.296+0800 ERROR Announcer-3 io.airlift.discovery.client.Announcer
通过模拟Vite一起深入其工作原理
随机推荐
How Jin Cang database correctness verification platform installation file
Multithreading (2)
Talking about data security governance and privacy computing
leetcode - a subtree of another tree
Use SuperMap iDesktopX data migration tool to migrate ArcGIS data
Dameng 8 database export and import
如何在WordPress中添加特定类别的小工具
Ffmpeg - sources analysis
One hundred - day plan -- -- DAY2 brush
sql server installation prompts that the username does not exist
Use SuperMap iDesktopX data migration tool to migrate map documents and symbols
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)
Cybersecurity and the Metaverse: Identifying Weak Links
Why is the pca component not associated
使用二维码传输文件的小工具 - QFileTrans 1.2.0.1
Syntax basics (variables, input and output, expressions and sequential statements)
【滤波跟踪】基于matlab无迹卡尔曼滤波惯性导航+DVL组合导航【含Matlab源码 2019期】
Simple description of linked list and simple implementation of code
语法基础(变量、输入输出、表达式与顺序语句完成情况)
AI + Small Nucleic Acid Drugs | Eleven Completes $22 Million Seed Round Financing