One, what is UnitTest
The unittest we're going to use here is the Python unit test framework, and its website is
Https://docs.python.org/2/library/unittest.html, here we can get comprehensive information.
As we write more and more use cases, we need to consider the specification and organization of use case writing for later maintenance, and unittest is just such a tool. Here we use an example to show what the UnitTest script looks like. You can do this by using the Selenium IDE's recording capabilities. Once the recording is complete, we will export the following steps.
Then execute the exported py file and get a message similar to the following:
---------------------------------------------------
Ran 1 Test in 12.801s
OK
We open the exported script to look at, recorded in Baidu search keyword Selenium2:
#-*-Coding:utf-8-*-from selenium import Webdriver to 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 #导入unittest包 import UnitTest, Time, re #SearchTest类继承自unittest. TestCase, indicating that this is a test case class Searchtest (UnitTest. TestCase): #setUp用于初始化工作 def setUp (self): Self.driver = Webdriver. Firefox () self.driver.implicitly_wait () Self.base_url = "https://www.baidu.com/" Self.verificati Onerrors = [] 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_e lement_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 = Ale Rt.text if Self.accept_next_alert:alert.accept () else:alert.dism ISS () return alert_text Finally:self.accept_next_alert = True #在每个测试方法后执行, complete cleanup work def Teardow N (self): Self.driver.quit () self.assertequal ([], self.verificationerrors) #整个测试过程集中在unittest的main () module, its default
To perform a method beginning with test if __name__ = = "__main__": Unittest.main ()
Through this we probably have an intuitive understanding of the unittest. Unittest.main (): Use it to turn a unit test module into a test script that can run directly, and the main () method uses the Testloader class to search for all test methods that are included in the module with the name "Test" and automatically execute. The default order of execution methods is to load test cases in order of ASCII code, with the order of numbers and letters: 0-9,a-z,a-z. Therefore, a test case method that begins with a takes precedence and executes after a begins. Ii. Concepts in the UnitTest
TestCase:
A testcase instance is a test case, and the test case is a complete test process, including initializing the setup, running run, and testing the restore teardown. UnitTest. TestCase class, the base class that all test case classes inherit. This class provides a number of assert methods for checking comparisons, in part as follows:
Most of the methods can be seen in their name, the use of the threshold is very low.
TestSuite:
Testing a function often requires multiple test cases, and can bring together more test cases to execute, which is the concept of testsuite. The common Addtest () method adds a test case to the test suite.
Texttestrunner:
is used to execute the test case, where run (test) is used to perform the testsuite/testcase. The results of the test are saved in the Texttestresult instance.
testfixture:
The work to be done before the test is prepared and the work to be done after the test is completed. Includes setup () and teardown (). Implemented by overwriting the TestCase setup and teardown.
With these key concepts in hand, we can change the last line in the previous script Unittest.main () to the following code:
#构造测试套件
suite = unittest. TestSuite ()
suite.addtest (Searchtest ("Test_search"))
#执行测试
runner = UnitTest. Texttestrunner ()
Runner.run (Suite)
After execution, the results are found to be the same as those previously used with Unittest.main (). III. Use-case organization
Here we assume that there are multiple testcase such as Test_case1,test_case2 ... in the script, so how do we control the order in which they are executed?
Execute test Case scenario one:
Executed directly with Unittest.main (), where it searches for all test case methods that start with testing and executes multiple use cases in the order of ASCII.
Execute test Case scenario two:
First instantiate the test suite, load the use case into it, and then use the Texttestrunner to execute the use case:
Suite=unittest. TestSuite ()
suite.addtest (Test (' Test_case2 '))
suite.addtest (Test (' test_case1 '))
runner=unittest. Texttestrunner ()
Runner.run (Suite)
The order of execution is the order in which the use cases are loaded, for example, after 2 execution 1 first.
Execute test Case scenario three:
In Scenario 2, if we have hundreds of use cases, one add in, it is not realistic, then we can use Defaulttestloader to load:
Test_dir = './'
discover = Unittest.defaultTestLoader.discover (Test_dir, pattern= ' *test.py ')
runner = UnitTest. Texttestrunner ()
Runner.run (Discover)
It uses./Specifies the current directory, specifies the *test.py file, executes the use cases in it, in the same order as the scenario.
If there are multiple. py files on a pattern match under the directory specified here. Call the Discover method, first through the TEST_DIR definition to find the directory, if the filename satisfies the defined pattern, then we use the For loop to find out all the filtered use cases and add them to the suite, the main code is as follows:
For Test_suite in Discover: for
test_case in Test_suite:
test_unit.addtests (Test_case)
The way we organize the use cases above we can see that in the actual test script development, we can create xx.py files in the directory, and when the use cases are stable, they can be modified into test_xx.py to add to the test suite. Note that the matching rules for file names can be defined arbitrarily by the pattern parameters.
If you want to perform a multilevel directory structure of Use cases. To be discover read Execute, we want to add _ init _.py file四、一个 example in the directory
The following is a simple introduction to a use case structure with unittest organization, first set up the D:\Test_Project directory, and then put Test_case and test_report to store use cases and reports separately.
1. Writing test Cases
Write use cases under Test_case, which is a simple example of how to search for keywords and click Settings on Baidu:
File name: test_baidu.py #-*-Coding:utf-8-*-from selenium import webdriver import unittest, time, re class MyTest (unittes T.testcase): def setUp (self): Self.driver = Webdriver. Firefox () self.driver.implicitly_wait () Self.base_url = "Https://www.baidu.com" Self.accept_next _alert = True def test_02baidu_search (self): U ' ' Test baidu search ' Driver = Self.driver Driver.get (s
Elf.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 ' ' Test Baidu home set ' Driver = SELF.D River Driver.get (Self.base_url + "/") Driver.find_element_by_css_selector ("Div#u1 a.pf"). Click () d River.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中调用时, do not have this if __name__ = ="
__main__ ": Unittest.main ()
To show the effect of the organization test case, we'll copy the file again, modifying the filename and method name, and so on:
File name: test_baidu2.py #-*-Coding:utf-8-*-from selenium import webdriver import unittest, time, re class MyTest (Unitte St. TestCase): U ' test Baidu's second use case ' Def setUp (self): Self.driver = Webdriver. Firefox () self.driver.implicitly_wait () Self.base_url = "Https://www.baidu.com" Self.accept_next _alert = True def test_02baidu_search (self): U ' Test test_02baidu_search ' driver = Self for the second use case of Baidu. 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 ' "' Test Baidu The second use case of test_01baidu_setting ' driver = Self.driver driver.get (self.base_url + "/") Driver.find_el
Ement_by_css_selector ("Div#u1 a.pf"). Click ()Driver.find_element_by_class_name ("Setpref"). Click () driver.find_element_by_css_selector ("Div#gxszB Utton>a.prefpanelgo "). Click () Driver.switch_to_alert (). Accept () print (" Test_baidu2__test_01baidu_settin G ") def teardown (self): Self.driver.close () if __name__ = =" __main__ ": Unittest.main ()
~
2. Landscaping report style and send results mail
We've written two test cases as examples, and we can add more. Then we use Htmltestrunner this open source module to beautify the test report, about its download use can refer to Https://pypi.python.org/pypi/HTMLTestRunner. Then, we can write in the code after the run is completed automatically send test mail out, easy to see. Please refer to the following code:
#coding =utf-8 Import unittest import smtplib from Email.mime.text import mimetext from Email.header import header import T
IME Import Htmltestrunner from email.mime.application import mimeapplication #---Send mail---def send_email (report_file): Sender = "XXXXXX@qq.com" receiver = "XXXXXX@qq.com" smtpserver = "smtp.qq.com" #发送邮箱的账号密码, here is the use of QQ mailbox and Third-party login authorization Code 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 "Automated Test Report" SMTP = Smtplib. Smtp_ssl ("smtp.qq.com") smtp.login (username, password) smtp.sendmail (sender, receiver, msg.as_string ()) smtp.q
Uit () print ("Email has send out!") #---Add a use case to the test suite---def creatsuite (): Testunit=unittest. TestSuite () Test_dir = "D:\\test_project\\test_case" discover = Unittest.defaultTestLoader.discover (Test_dir, Patt Ern= "test*.py", Top_level_dir = None) for test_suite in Discover:for test_ Case in Test_suite:testunit.addTest (test_case) print (testunit) return testunit if __name__ = = "__main__": Current_time = Time.strftime ("%y-%m-%d-%h-%m") Report_dir = "d:\\test_project\\test_report\\" R Eport_file = report_dir + current_time + "-test_result.html" Report_stream = open (Report_file, "WB") # runner = UN Ittest. Texttestrunner () # Note that Htmltestrunner only supports python2 runner = Htmltestrunner.htmltestrunner (Stream=report_stream,title=u " Automated Test Report ", description=u" use case execution is as follows: "Runner.run (Creatsuite ()) Report_stream.close () Send_email (Report_file)
In the above code we use the runner = Htmltestrunner.htmltestrunner () method instead of runner = UnitTest. Texttestrunner (), is to use Htmltestrunner this module to beautify and output beautiful report. Then call the method to send the message. After running this file, you can get the following output reports:
You can see that you can use this to clearly see the execution of the use case, and to debug it by looking at the reason for the failed use case.
Also, a notification message is received in the Inbox we entered, and we can add this output report to the body or attachment of the message for easy viewing.