当前位置:网站首页>[test development] automated test selenium (III) -- unittest framework analysis
[test development] automated test selenium (III) -- unittest framework analysis
2022-06-13 03:39:00 【Bryant tapping the code】
【 Test Development 】 automated testing selenium( 3、 ... and )——unittest Framework analysis
unittest Framework analysis
unittest yes python The unit test framework of , stay python In the official documents of , Yes unittest There is a detailed introduction , Students who want to further study can go to https://www.python.org/doc/ To understand .
unittest Unit testing provides the ability to create test cases , Test suite and batch execution scheme , unittest In the installation pyhton I'll bring it myself , direct import unittest You can use .
As a framework for unit testing , unittest It is also an agile test of the smallest module of the program . In automated testing , We don't need to do a white box test , But you need to know the unit test framework of the language you use . Using unit test framework , Create a class , Inheritance of such kind unittest Of TestCase, So that we can case As a minimum unit , Organized by test containers , When the time comes, execute directly , At the same time, the test report is introduced .
unittest The relationship of each component is :
- test fixture: Test firmware , Initialize and clean up the test environment , Like creating a temporary database , Files and directories, etc , among
setUp() and setDown()Is the most commonly used method - test case: Unit Test Case ,TestCase It is the most commonly used class for writing unit test cases
- test suite: test suite ,
A collection of unit test cases ,TestSuite Is the most commonly used class - test runner: Perform unit tests
- test report: Generate test reports
unittest and Junit The difference betweenTesting firmware is simple :
import time
from selenium import webdriver
import unittest
class Test(unittest.TestCase):
# Test Inherited from unittest.TestCase
# Test firmware setup and tearDown
# there self It is equivalent to an example
def setUp(self):
self.driver = webdriver.Chrome()
self.url = "http://www.baidu.com/"
self.driver.maximize_window()
def tearDown(self):
self.driver.quit()
# The test method name must be test_ Otherwise, it will not be carried out
def test_baidu(self):
driver = self.driver
driver.get(self.url)
driver.find_element_by_id("kw").send_keys("kobe")
driver.find_element_by_id("su").click()
time.sleep(3)
if __name__ == "__main__":
unittest.main(2)
''' Can increase verbosity Parameters , for example unittest.main(verbosity=2) In the main function , Call directly main() , stay main Add verbosity=2 , In this way, the test results will be displayed in more detail . there verbosity It's an option , Represents the information complexity of the test results , There are three values : 0 ( silent mode ): You can only get the total number of test cases and total results, such as a total of 100 A failure ,20 success 80 1 ( The default mode ): It's very similar to the silent mode, except that there is a... In front of each successful use case “ . ” Each failed use case is preceded by a “F” 2 ( Detailed mode ): The test results show all the relevant information for each test case '''

Batch script execution
Build test suite
Complete unit tests rarely execute only one test case , Developers usually need to write multiple test cases to test a software function completely , These related test cases are called a test case set , stay unittest Medium used TestSuite Class .
Suppose we have written testbaidu1.py,testbaidu2.py Two documents , So how can we execute these two files at the same time ?
addTest() Application
When there are multiple or hundreds of test cases , This requires a test container ( test suite ) , Put the test case in the container for execution ,unittest Module provides TestSuite Class to generate the test suite , Using the constructor of this class, you can generate an instance of the test suite , This class provides addTest To add each test case to the test suite .
take testbaidu1.py、testbaidu2.py、runall.py Put it in the same directory testcase in
runall.py The contents are as follows
import time
# Import test_baidu1,test_baidu2
import test_baidu1
import test_baidu2
import unittest
# Manually add cases to the suite ,
def createsuite():
suite = unittest.TestSuite()
# Add test cases to the test container ( Kit ) in
suite.addTest(test_baidu1.Baidu1("test_baidu1"))
suite.addTest(test_baidu2.Baidu2("test_baidu2"))
return suite
if __name__ == "__main__":
suite = createsuite()
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

There are two aspects of the above approach , Hinder the rapid execution of scripts , Must be modified every time runall.py:
1) You need to import all py file , such as import testbaidu1, Each new one needs to be imported
2)addTest Need to add all testcase, If one py In file 10 individual case, It needs to be increased 10 Time
makeSuite() and TestLoader() Application
stay unittest The framework provides makeSuite() Methods ,makeSuite It can realize all the tests in the test case class case Test suite composed of TestSuite ,unittest call makeSuite When , Just pass in the test class name .
TestLoader Test suite for creating classes and modules
In general , send TestLoader().loadTestsFromTestCase(TestClass) To load the test class .
runall.py The contents are as follows
import time
# Import test_baidu1,test_baidu2
import test_baidu1
import test_baidu2
import unittest
# Manually add cases to the suite ,
def createsuite():
suite = unittest.TestSuite()
# Add test cases to the test container ( Kit ) in
suite.addTest(unittest.makeSuite(test_baidu1.Baidu1))
suite.addTest(unittest.makeSuite(test_baidu2.Baidu2))
return suite
''' suite1 = unittest.TestLoader().loadTestsFromTestCase(test_baidu1.Baidu1) suite2 = unittest.TestLoader().loadTestsFromTestCase(test_baidu2.Baidu2) suite = unittest.TestSuite([suite1, suite2]) return suite '''
if __name__ == "__main__":
suite = createsuite()
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

after makeSuite() and TestLoader() The introduction of , We don't need one py File test class , You only need to import it once .
So can you test classes without adding specifications every time ?
discover() Application
discover Is recursively to its subdirectory, starting from the specified directory , Find all test modules and return an object containing them TestSuite , Then load the only test file matching the pattern ,discover The parameters are discover(dir,pattern,top_level_dir=None)
runall.py— Pay attention to the path
# -*- coding: utf-8 -*-
import unittest,csv
import os,sys
import time
# Manually add cases to the suite ,
def createsuite():
discover=unittest.defaultTestLoader.discover('../test',pattern='test*.py',top_level_dir=None)
print discover
return discover
if __name__=="__main__":
suite=createsuite()
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
Use case execution sequence
unittest By default, the order in which the framework loads test cases is based on ASCII The order of the codes , The order of numbers and letters is : 09,AZ,a~z
therefore , TestAdd Class will take precedence over TestBdd Class is found , test_aaa() Method will take precedence over test_ccc() Be performed .
For test directories and test files , unittest The framework also loads test cases according to this rule .addTest() Methods are executed in increasing order .
Ignore use case execution
@unittest.skip("skipping")
Adding this comment before the test method is to ignore the use case execution
unittest Assertion
Automated testing , For each individual case Come on , One case In the execution result of , There must be expected results and actual results , To judge the right case Pass or fail , stay unittest The library provides a number of practical ways to check expected and actual values , To verify case Result , Generally speaking , The inspection conditions are roughly divided into equivalence , Logical comparison and other , If the given assertion passes , The test will continue to the next line of code , If the assertion fails , Corresponding case The test will stop immediately or generate an error message ( Generally, you can print error messages ) , But don't affect others case perform .
unittest The unit test library provides a standard xUnit assert methods . Here are some common assertions
| Serial number | assert methods | Assertion description |
|---|---|---|
| 1 | assertEqual(arg1, arg2, msg=None) | verification arg1=arg2, If you don't wait fail |
| 2 | assertNotEqual(arg1, arg2, msg=None) | verification arg1 != arg2, Equal is equal fail |
| 3 | assertTrue(expr, msg=None) | verification expr yes true, If false, be fail |
| 4 | assertFalse(expr,msg=None) | verification expr yes false, If true, be fail |
| 5 | assertIs(arg1, arg2, msg=None) | verification arg1、arg2 Is the same object , Not so fail |
| 6 | assertIsNot(arg1, arg2, msg=None) | verification arg1、arg2 Not the same object , it is then fail |
| 7 | assertIsNone(expr, msg=None) | verification expr yes None, Not so fail |
| 8 | assertIsNotNone(expr, msg=None) | verification expr No None, it is then fail |
| 9 | assertIn(arg1, arg2, msg=None) | verification arg1 yes arg2 The string of , Not so fail |
| 10 | assertNotIn(arg1, arg2, msg=None) | verification arg1 No arg2 The string of , it is then fail |
| 11 | assertIsInstance(obj, cls, msg=None) | verification obj yes cls Example , Not so fail |
| 12 | assertNotIsInstance(obj, cls, msg=None) | verification obj No cls Example , it is then fail |
import time
from selenium import webdriver
import unittest
class Baidu1(unittest.TestCase):
# Test Inherited from unittest.TestCase
# Test firmware setup and tearDown
# there self It is equivalent to an example
def setUp(self):
self.driver = webdriver.Chrome()
self.url = "http://www.baidu.com/"
self.driver.maximize_window()
def tearDown(self):
self.driver.quit()
# The test method name must be test_ Otherwise, it will not be carried out
def test_baidu1(self):
driver = self.driver
driver.get(self.url)
driver.find_element_by_id("kw").send_keys("kobe")
driver.find_element_by_id("su").click()
# Add assertions
self.assertEqual("kobe", driver.find_element_by_link_text(" Kobe · Bryant - Baidu Encyclopedia ").text,msg="kobe!= Kobe · Bryant - Baidu Encyclopedia ")
time.sleep(3)
if __name__ == "__main__":
unittest.main(2)
''' Can increase verbosity Parameters , for example unittest.main(verbosity=2) In the main function , Call directly main() , stay main Add verbosity=2 , In this way, the test results will be displayed in more detail . there verbosity It's an option , Represents the information complexity of the test results , There are three values : 0 ( silent mode ): You can only get the total number of test cases and total results, such as a total of 100 A failure ,20 success 80 1 ( The default mode ): It's very similar to the silent mode, except that there is a... In front of each successful use case “ . ” Each failed use case is preceded by a “F” 2 ( Detailed mode ): The test results show all the relevant information for each test case '''

Can pass IDE To add assertions :
HTML Report generation
After the script is executed , Still need to see HTML The report , Let's go through HTMLTestRunner.py To generate test reports .
HTMLTestRunner Support python2.7.python3 See the code in the following website , Copy and paste between https://blog.csdn.net/liubo37/article/details/105069609/
HTMLTestRunner.py file , Download address :
http://tungwaiyip.info/software/HTMLTestRunner.html
After downloading, put it in testcase To go or put into a directory …\Python27\Lib Under the table of contents (windows).
modify runall.py
# -*- coding: utf-8 -*-
import unittest,csv
import os,sys
import time
import HTMLTestRunner
# Manually add cases to the suite ,
def createsuite():
discover=unittest.defaultTestLoader.discover('../test',pattern='test*.py',top_level_dir=None)
print discover
return discover
if __name__=="__main__":
curpath=sys.path[0]
# Solve the problem of duplicate naming
now=time.strftime("%Y-%m-%d-%H %M %S",time.localtime(time.time()))
# Under the current path resulreport Create a folder when it doesn't exist
if not os.path.exists(curpath+'/resultreport'):
os.makedirs(curpath+'/resultreport')
# The file name is the path plus the name of the file
# Get ready HTML Report output file
filename=curpath+'/resultreport/'+now+'resultreport.html'
# open HTML file ,wb In writing
with open(filename,'wb') as fp:
# Out html The report , The parameters in parentheses are HTML The parameters in the report
runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title=u' Test report ',description=u' Use case execution
situation ',verbosity=2)
suite=createsuite()
runner.run(suite)


Exception capture and error screenshot
Use cases cannot succeed every time they run , There must be some unsuccessful times when it runs . If you can catch errors , And save the error screenshot , This will be a great feature , It will also bring convenience to our wrong positioning .
For example, write a screenshot function , The key statement is driver.get_screenshot_as_file:
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()))
# Screenshot save
driver.get_screenshot_as_file('./image/'+now+'-'+file_name)
time.sleep(1)
A quoted example :
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
import os
class Baidu1(unittest.TestCase):
#test fixture, Initialization environment
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "http://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True
# The test case , Must be test start
def test_hao(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_link_text("hao123").click()
time.sleep(2)
try:
self.assertEqual(u'hao_ Internet starts here ', driver.title)
except:
self.savescreenshot(driver,'hao.png')
# Judge element Whether there is , Deleting
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
# Judge alert Whether there is , Deleting
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
# close alert, Deleting
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
#test fixture, Clear the environment
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
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()))
# Screenshot save
driver.get_screenshot_as_file('./image/'+now+'-'+file_name)
time.sleep(1)
if __name__ == "__main__":
# Execute use cases
unittest.main()
''' Can increase verbosity Parameters , for example unittest.main(verbosity=2) In the main function , Call directly main() , stay main Add verbosity=2 , In this way, the test results will be displayed in more detail . there verbosity It's an option , Represents the information complexity of the test results , There are three values : 0 ( silent mode ): You can only get the total number of test cases and total results, such as a total of 100 A failure ,20 success 80 1 ( The default mode ): It's very similar to the silent mode, except that there is a... In front of each successful use case “ . ” Each failed use case is preceded by a “F” 2 ( Detailed mode ): The test results show all the relevant information for each test case '''
边栏推荐
- Prefecture level city - air flow coefficient data - updated to 2019 (including 10m wind speed, boundary height, etc.)
- Summary of virtualization technology development
- IP address and classification
- Simulink代码生成: 查表模块及其代码
- C语言程序设计——从键盘任意输入一个字符串,计算其实际字符个数并打印输出,要求不能使用字符串处理函数strlen(),使用自定义子函数Mystrlen()实现计算字符个数的功能。
- Multithreaded chat room, server and client
- Byte stream & buffer stream
- Summary of rust language practice
- MySQL learning summary 9: non empty constraints, uniqueness constraints, primary key, auto_ Increment, foreign key, default, etc
- Data of all bank outlets in 356 cities nationwide (as of February 13, 2022)
猜你喜欢
![[azure data platform] ETL tool (5) -- use azure data factory data stream to convert data](/img/5c/79319a73881b645edaca77990f68a8.jpg)
[azure data platform] ETL tool (5) -- use azure data factory data stream to convert data

Explain usage, field explanations, and optimization instances of MySQL

Azure SQL db/dw series (13) -- using query store (2) -- report Introduction (2)

Video playback has repeatedly broken 1000w+, how to use the second dimension to create a popular model in Kwai

LVS四层负载均衡集群(5)LVS概述

Brief introduction: distributed cap theory and base theory
![[azure data platform] ETL tool (6) -- re understanding azure data factory](/img/b5/da5dc9815fb9729fb367f2482913b7.jpg)
[azure data platform] ETL tool (6) -- re understanding azure data factory

Simulink code generation: simple state machine and its code
![[azure data platform] ETL tool (1) -- Introduction to azure data factory](/img/0c/cd054c65aee6db5ae690f104db58a3.jpg)
[azure data platform] ETL tool (1) -- Introduction to azure data factory

Workflow of driver of spark kernel (stage division, task division, task scheduling)
随机推荐
The latest summary of key topics of journal C in 2022 - topic scope, contribution method and journal introduction
Multi thread implementation of selling tickets and producers and consumers
MySQL transaction isolation level experiment
Union, intersection and difference sets of different MySQL databases
Feign based remote service invocation
[azure data platform] ETL tool (8) - ADF dataset and link service
2000-2019 enterprise registration data of all provinces, cities and counties in China (including longitude and latitude, registration number and other multi indicator information)
Azure SQL db/dw series (12) -- using query store (1) -- report Introduction (1)
MySQL auto sort function deny_ rank() over()、rank() over()、row_ Num() over() usage and differences
Doris data backup and recovery
Database object, sequence, view, index
Graph data modeling tool
Azure SQL db/dw series (14) -- using query store (3) -- common scenarios
【测试开发】用例篇
Application framework / capability blueprint
[azure data platform] ETL tool (6) -- re understanding azure data factory
19 MySQL database optimization methods
Pollution discharge fees of listed companies 2010-2020 & environmental disclosure level of heavy pollution industry - original data and calculation results
(九)详解广播机制
Economic panel topic 1: panel data of all districts and counties in China - more than 70 indicators such as population, pollution and agriculture (2000-2019)

