First you need to know what Selenium is.

Selenium is a browser-based test automation tool that provides a cross-platform, cross-browser, end-to-end Web automation solution. Selenium mainly includes three parts: Selenium IDE, Selenium WebDriver and Selenium Grid.

  • Selenium IDE: A Firefox extension that records playback and exports recorded actions as test cases in a variety of languages such as Java, Python, and so on.

  • Selenium WebDriver: Provides apis required for Web automation, primarily for browser control, page element selection, and debugging. Different browsers require different Webdrivers.

  • Selenium Grid: Provides the ability to run Selenium tests on different browsers on different machines.

Next, I will use the mind map directory structure to introduce the basic testing framework, write test cases for functional test cases, hoping to help you learn.

Design ideas

The framework uses PYTHON3 + SELENium3 + PO + YAML + DDT + UNITtest and other techniques to write the basic test framework, which can adapt to the needs of daily testing.

  1. Page Object mode is used to separate Page positioning and business operations, separate test objects (element objects) and test scripts (use case scripts), and build an Object class for each Page to improve the maintainability of use cases;

  2. Manage page control element data and test case data using YAML. For example, when the element ID changes, there is no need to modify the test code, just need to modify in the corresponding page element YAML file.

  3. Module management, do not affect each other, assembly at any time, take and use.

The test framework is designed in layers

Encapsulate common operations and lookups into basic classes that can be reused, no matter what the product

  • The business layer is mainly to encapsulate the object page class, a page to build a class, the business layer page inherit the base layer

  • The use case layer constructs mock execution tests against product page functionality

  • The framework layer provides basic components to support the execution and function expansion of the whole process, and provides element data of each page, test data of use cases, test report output and so on for the use case layer

Test the framework directory structure

The following mind map directory structure is introduced:

Write use case methods

If software testing, interface testing, automated testing, interview experience exchange. Interested can pay attention to our programmer, there will be free information links in the public number from time to time, these information are collected from various technical websites, sorted out, if you have good learning materials can be private chat to send me, I will indicate the source after sharing with you.

Testinfo: -id: test_login001 title: login testinfo: open the front page testcase: -element_info: login-link-a find_type: ID operate_type: click info: open the login dialog box. -element_info: mobile find_type: ID operate_type: send_keys info: -element_info: MBPWD find_type: ID operate_type: send_keys info: Enter the password. -element_info: //input[@class='keeplogin'] find_type: XPATH operate_type: click info: click to cancel automatic login. //span[text()=' login '] find_type: XPATH operate_type: click info: click on the login button -element_info: userProNick find_type: -element_info: //a[@class='logout'] find_type: XPATH operate_type: click info: Check: -element_info: //div[@class='box-mobilelogin'] /div[1]/span find_type: XPATH info: -element_info: userProNick find_type: ID info: Login is successful. -element_info: reg-link-a find_type: ID info: Check whether login.yaml is logged out successfullyCopy the code

For example, let’s add a login function test case:

First, just add a page object yaml file in the TestyAML directory and write it in the login.yaml format. These files are provided to the wrapper page object class to call and perform location recognition operations.

-ID: test_login001.1 detail: Mobile phone number and password blank login screenshot: phone_pawd_empty data: phone: "" password: "" "check: - Phone number cannot be empty - id: test_login001.2 detail: phone number is empty login screenshot: phone_empty data: phone: "" password: AA check: - Mobile phone number cannot be empty - ID: test_login001.3 detail: Password is empty login screenshot: pawd_empty Data: phone: 13511112222 password: "" Check: - Password cannot be empty - id: test_login001.4 detail: invalid phone number login screenshot: phone_error data: phone: ABC password: AA check: - Phone number format is not correct. - ID: test_logIN001.5 detail: Phone number or password does not match screenshot: pawd_error Data: phone: 13511112222 Password: Aa check: - Account password error - ID: test_login001.6 detail: phone number and password correct screenshot: phone_pawd_success data: phone: 13865439800 password: ******** check : - yingoja login_data.yaml login_data.yamlCopy the code

Second, add a login_data.yaml file to the testdata directory to provide the testdata that the login interface transmits. The format is described in the login_data.yaml file.

#! /usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(os.path.dirname (os.path.dirname(__file__)))) from config import setting from selenium.webdriver.support.select import Select from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from public.page_obj.base import Page from time import sleep from public.models.GetYaml import getyaml testData = getyaml(setting.TEST_Element_YAML + '/' + 'login.yaml') class Url = '/' dig_login_button_loc = (by.id, testdata.get_elementInfo (0)) def dig_login(self): """ home login :return: Self.find_element (*self.dig_login_button_loc).click() sleep(1) Login_phone_loc = (by. ID, testdata.get_elementInfo (1)) # password_loc = Keeplogin_button_loc = (by.xpath, testData.get_elementInfo (3)) # Click login Login_exit_loc = (by. XPATH, testdata.get_elementinfo (4)) Testdata.get_elementinfo (5)) # select exit login_exit_button_loc = (by.xpath, testdata.get_elementInfo (6))def Login_phone (self,phone): "" param username: :return: """ self.find_element(*self.login_phone_loc). send_keys(phone)def login_password(self,password): Login password: param password: :return: Self.find_element (*self.login_password_loc).send_keys (password) def keeplogin(self): """ self.find_element(*self.login_password_loc).send_keys (password) def keeplogin(self): """ Self.find_element (*self.keeplogin_button_loc).click ()def login_button(self): "" Self.find_element (*self.login_user_loc).click() def login_exit(self): """ """ above = self.find_element(*self.login_exit_loc) ActionChains(self.driver).move_to_element(above). perform() sleep(2) Self.find_element (*self.login_exit_button_loc).click()def user_login(self,phone,password): "" Username :param password: Password :return """ self.open() self.dig_login() self.login_phone(phone) self.login_password(password) sleep(1) self.keeplogin() sleep(1) self.login_button() sleep(1) phone_pawd_error_hint_loc = (By.XPATH,testData. get_CheckElementinfo(0)) user_login_success_loc = (By.ID,testData. get_CheckElementinfo(1)) exit_login_success_loc = (By.ID,testData. Def phone_pawd_error_hint(self): Def user_login_success_hint(self): return self.find_element(*self.phone_pawd_error_ hint_loc). Return self.find_element(* self.user_login_success_loc). Text def exit_login_success_hint(self): return self.find_element(*self.exit_login_ success_loc).textloginPage.pyCopy the code

Then, add a loginpage.py file in the page_obj directory to encapsulate the loginPage object class and perform the login test flow operations.

#! /usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(os.path. dirname(__file__))) import unittest,ddt,yaml from config import setting from public.models import myunit,screenshot from  public.page_obj.loginPage import login from public.models.log import Log try: f =open(setting.TEST_DATA_YAML + '/' + 'login_data.yaml',encoding='utf-8') testData = yaml.load(f) except FileNotFoundError as file: log = log () log.error(" file not found: {0}".format(file)) @ddt. DDT class Demo_UI(myunit.mytest): Def user_login_verify(self,phone,password): """ def user_login_verify(self,phone,password): """ "user login :param phone: phone number :param password: password: return: User_login (phone,password) def exit_login_check(self): """ """ login(self.driver).login_exit() @ddc.data (*testData) def test_login(self,datayaml): Return: """ log = log () log.info(" current test case ID-> {0}; Format (datayaml['id'],datayaml['detail'])) self.user_login_verify(datayaml['data']['phone'], datayaml['data']['password']) po = login(self.driver) if datayaml['screenshot'] == 'phone_pawd_success': Log.info (" checkpoint -> {0}". Format (po.user_login_success_hint())) self.assertequal (po.user_login_success_hint(), Format (po.user_login_success_hint())) log.info(" login_success_hint() ") datayaml['check'][0], "successful login, return result ->: {0}". {0}".format(po.user_login_success_hint())) screenshot.insert_img(self.driver, Datayaml ['screenshot'] + '.jpg') log.info("-----> start executing exit process operation ") self.exit_login_check() po_exit = login(self.driver) Log.info (" Checkpoint -> find {0} element, exit successful!" .format(po_exit_login_success_hint ())) self.assertequal (po_exit_login_success_hint (), 'register '," {0}". Format (po_exit_login_success_hint ())) log.info {0}".format(po_exit.exit_login_success_hint())) else: Log.info (" checkpoint -> {0}".format(po.phone _pawd_error_hint())) self.assertequal (po.phone_pawd_error_hint(), Format (po.phone_pawd_error_hint())) log.info(" datayaml['check'][0], "->: {0}". {0}".format(po.phone_pawd_error_hint())) screenshot.insert_img(self.driver,datayaml ['screenshot'] + '.jpg') if __name__=='__main__': unittest.main() login_sta.pyCopy the code

Finally, the testcase file login_sta.py is created in the testcase directory, and the yaml test data file is read using DDT data driver

To sum up, writing a use-case method is just a matter of following these four steps: Create -> Write.

Execute the following main program, you can see the actual output results.

#! /usr/bin/env python # _*_ coding:utf-8 _*_ __author__ = 'YinJia' import os,sys sys.path.append(os.path.dirname(__file__)) from config import setting import unittest,time from package.HTMLTestRunner import HTMLTestRunner from public.models.newReport import new_report from public.models.sendmail import send_mail # Test report folder, if it does not exist, If not os.path.exists(setting.TEST_REPORT):os.makedirs (setting.TEST_REPORT + '/' + "screenshot") def add_case(test_path=setting.TEST_DIR): "" "to load all the test cases ", "" discover = unittest. DefaultTestLoader. Discover (test_path, pattern='*_sta.py') return discover def run_case(all_case,result_path=setting.TEST_REPORT): "" "to perform all the test cases ". "" now = time strftime (" % Y - % m M_ H_ - % d % % % S") filename = result_path + + now, '/' 'result. HTML' fp = Open (filename,'wb') runner = HTMLTestRunner(stream=fp,title=' UI Automatic test report ', description=' chrome', Tester ='Jason') runner. Run (all_case) fp.close() report = new_report(setting.test_report) # call email module if __name__ = = "__main__" : cases = add_case () run_case (cases)Copy the code

Test results presentation

HTML report log

HTML Report Click screenshot to pop up screenshot

Log that the test report passes

Automatic screenshots are saved to the specified directory

Email Test Report

I wish you and I meet, both gain!