Python + Selenium notes (13): Page Object design mode, pythonselenium
(1)Preface
To put it simply, there are two layers: page class and test class.
Page class: divided into parent class and Child class (subclass refers to a specific page, each page creates a class), the parent class defines public attributes and methods (operations ).
# If you have an understanding of object-oriented, you should easily understand the meaning of abstracting public attributes and methods.
# I describe the parent class and subclass based on my own understanding, or I can say that the basepage object (parent object, providing public attributes and methods) and page Object (specific page)
Test class: combines the attributes and operations of each page according to the business process to form a test case.
Use the page object Mode to abstract the elements and methods of each page, and then combine them according to the requirements of test cases. The advantage of doing so is that
1. After the page is modified, you only need to modify the page class, which has no significant impact on the test class (test case ).
2. Some code can be reused in multiple tests.
3. The test code (test class and test case) is easier to read, flexible, and maintained.
I modified the previous code in the page object mode. The Code is as follows.
(2)Parent class (BasePage object, base. py)
1 from abc import abstractclassmethod 2 class BasePage (object): 3 def _ init _ (self, driver): 4 self. driver = driver 5 6''': Check whether the page is specified. 7 @ abstractclassmethod modifier indicates that the method is abstract '''8 @ abstractclassmethod 9 def validate_page (self, driver): 10 return
(3)Homepage (page Object (subclass), homepage. py)
1 from base import BasePage 2 class HomePage (BasePage ): 3 #4 _ login_area = '# login_area '5 _ register = 'register '6 7 def validate_page (self, driver): 8 return driver. title = 'blog garden-developer's online home' 9 # locate and click Register 10 def register_click (self): 11 self. login_area = self. driver. find_element_by_css_selector (self. _ login_area) 12 self. login_area.find_element_by_link_text (self. _ register ). click ()
(4)Registration page (page Object (subclass), registerpage. py)
1 from base import BasePage 2 class RegisterPage (BasePage ): 3 #4 _ user_email = 'email '5 _ user_phone_country = 'countrycode' 6 _ user_phone = 'phonenum' 7 _ user_login_name = 'loginname' 8 _ user_nickname = 'displayname' 9 _ user_password = 'Password' 10 _ user_confirm_password = 'confirmpassword' 11 _ phone_error = 'phonenum-error' 12 _ loginName_error = 'loginname -error '13 14 def validate_page (self, driver): 15 return driver. title = 'user registration-blog service' 16 17 # Enter registration information 18 def send_keys (self, email, phone, login_name, nickname, password, confirm_password): 19 self. driver. find_element_by_id (self. _ user_email ). clear () 20 self. driver. find_element_by_id (self. _ user_phone ). clear () 21 self. driver. find_element_by_id (self. _ user_login_name ). clear () 22 self. driver. find_element_by_id (self. _ user_nickname ). clear () 23 self. driver. find_element_by_id (self. _ user_password ). clear () 24 self. driver. find_element_by_id (self. _ user_confirm_password ). clear () 25 self. driver. find_element_by_id (self. _ user_email ). send_keys (email) 26 self. driver. find_element_by_id (self. _ user_phone ). send_keys (phone) 27 self. driver. find_element_by_id (self. _ user_login_name ). send_keys (login_name) 28 self. driver. find_element_by_id (self. _ user_nickname ). send_keys (nickname) 29 self. driver. find_element_by_id (self. _ user_password ). send_keys (password) 30 self. driver. find_element_by_id (self. _ user_confirm_password ). send_keys (confirm_password) 31 32 # prompt message when the phone number is incorrect 33 def phone_err (self): 34 phone_error = self. driver. find_element_by_id (self. _ phone_error) 35 return phone_error.text36 37 # message displayed when the logon name is invalid 38 def loginName_error (self): 39 loginName_error = self. driver. find_element_by_id (self. _ loginName_error) 40 return loginName_error.text
(5)Test class (test case, testRegisterNewUser. py)
1 from selenium import webdriver 2 from ddt import ddt, data, unpack 3 import xlrd 4 from homepage import HomePage 5 from registerpage import RegisterPage 6 from basetestcase import BaseTestCase 7 # function 8 def get_data (file_name) for reading Excel Data ): 9 rows = [] 10 book = xlrd. open_workbook (file_name) 11 sheet = book. sheet_by_index (0) 12 for r_idx in range (1, sheet. nrows): 13 rows. append (list (sheet. row_values (r_idx, 0) 14 pthone = rows [r_idx-1]. pop (1) 15 rows [r_idx-1]. insert (1, str (int (pthone) 16 return rows17 @ ddt18 class RegisterNewUserDDT (BaseTestCase): 19 # rewrite setUpClass () 20 @ classmethod21 def setUpClass (cls ): 22 cls. driver = webdriver. chrome () 23 cls. driver. implicitly_wait (30) 24 cls. driver. maximize_window () 25 cls. driver. get ('https: // www.cnblogs.com/') 26 # create an object instance of the HomePage () Class 27 home_page = HomePage (cls. driver) 28 home_page.register_click () 29 # read data from an excel file as the parameter 30 @ data (* get_data ('data/reTest.xlsx ') 31 @ unpack32 def test_register_new_user (self, email, phone, login_name, nickname, password, confirm_password, expected_result): 33 # create RegisterPage () object instance 34 register_page = RegisterPage (self. driver) 35 self. assertTrue (register_page.validate_page (self. driver) 36 register_page.send_keys (email, phone, login_name, nickname, password, confirm_password) 37 if phone = '1': 38 self. assertTrue (register_page.phone_err () = expected_result) 39 elif login_name = 'B': 40 self. assertTrue (register_page.loginName_error () = expected_result)
(6)Test preparation (basetestcase. py)
# This part was originally intended to be placed in step 2, but it may affect the understanding of the page object.
Create a class and define the setup () and teardowm () methods to facilitate reuse of all tests. This class can be understood as part of the test class. I just used setup () and teardowm () for all test classes (test cases) to facilitate reuse. You can rewrite a test case if it has special requirements.
1 import unittest 2 from selenium import webdriver 3 4 class BaseTestCase(unittest.TestCase): 5 @classmethod 6 def setUpClass(cls): 7 cls.driver = webdriver.Chrome() 8 cls.driver.implicitly_wait(30) 9 cls.driver.maximize_window()10 cls.driver.get('https://www.cnblogs.com/')11 @classmethod12 def tearDownClass(cls):13 cls.driver.quit()