Steps and summary of building a data-driven automated testing framework from scratch using python webdriver

Step by step process and summary of building a data-driven testing framework

After learning from Mr. Wu to build an automated data-driven framework, when I was practicing on my own, I tried to expand and optimize the simple program bit by bit to implement this data-driven framework.

Let’s first talk about the purpose of building an automated testing framework:

One is to realize the automated operation of a function without having to manually perform some repetitive work every time. Use automated programs to replace manual work and improve efficiency, such as repeated execution of regression tests.

The second is to encapsulate the data and operations on the data, reduce the writing of repeated codes, and separate the test data and programs, so that automated testers do not need to pay too much attention to the code.

By maintaining the data well, you can carry out effective automated test execution, good reusability, and many other benefits. . .

Let me talk about the summary of the process after I built this framework from scratch:

First implement the function to be implemented in a file, then encapsulate a certain scattered function, call the encapsulated method in the main program, and divide the whole process into multiple steps. Each step only implements one encapsulation or optimization.

Just like placing building blocks, after completing a place, stand at this node and think about what I can encapsulate and optimize next, then take a step forward, and then consider what can be optimized on this basis.

Until the test framework is built, the process is first separated from the framework structure. Instead of thinking about what the framework is going to be like, we just think about what encapsulation and optimization can be done with the existing program, and how to change it to make it more usable. convenient,

It looks more organized, and then when I think about what parts can be extracted to make separate packages, I will compare some framework structures and what kind of packages this type of package can be placed under. I will optimize the package and classify it at the same time.

When we encapsulate the program and put it in the configuration file, we put it in the configuration file. In the end, you will find that what you get from this process is a testing framework.

After this process is completed, it will be much easier to understand the function of each module from the overall architecture of the test framework, because when you optimize and encapsulate it from scratch, you will finally get these modules.

Then when you learn test frameworks for different driver types, the principles are basically the same.

Here is the overall process of building this framework:
First of all, it is clear that what I want to achieve is the function of logging into the 126 mailbox and adding contacts.


Step 1--If I don't use the framework and list the code directly, how can I achieve it? Let's try to complete this first. Create
a new project in pycharm -dataDrivenTestPractice1.
Create a new TestScript package under the project.
Create a TestScript package under the TestScript package. python file

code:
#encoding=utf-8
#author-Xia Xiaoxu
from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import traceback

driver=webdriver.Firefox(executable_path='c:\\geckodriver')
driver.get('http://mail.126.com')
try:
    wait=WebDriverWait(driver,10,0.2)#Show waiting
    driver.switch_to.frame(driver.find_element_by_xpath("//iframe[@id='x-URS-iframe']"))#Switch to the frame element where the user name and password input box is located name=wait.until(lambda x
    : x.find_element_by_xpath("//input[@placeholder='Email account or mobile phone number' and @name='email']"))
    name.send_keys('xiaxiaoxu1987')
    password=wait.until(lambda x:x.find_element_by_xpath ("//input[@placeholder='password']"))
    password.send_keys('gloryroad')
    submit=wait.until(lambda x:x.find_element_by_xpath("//a[@id='dologin']" ))
    submit.click()
    driver.switch_to.default_content()#Using switch_to_default_content() in pycharm will be strikethrough, and
    time.sleep(5)
    assert u"exit" in driver.page_source,"no exist in page_source"
    address_book_link=wait.until(lambda x:x.find_element_by_xpath("//div[text()='通讯录']"))
    address_book_link.click()
    #assert u"新建联系人" in driver.page_source
    add_contact_button=wait.until(lambda x:x.find_element_by_xpath("//span[text()='新建联系人']"))
    add_contact_button.click()
    contact_name=wait.until(lambda x:x.find_element_by_xpath("//a[@title='编辑详细姓名']/preceding-sibling::div/input"))
    contact_name.send_keys(u"徐凤钗")
    contact_email=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_MAIL_wrap']//input"))
    contact_email.send_keys("[email protected]")
    contact_is_star=wait.until(lambda x:x.find_element_by_xpath("//span[text()='Set as star contact']/preceding-sibling::span/b"))
    contact_is_star.click()
    contact_mobile=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input"))
    contact_mobile.send_keys('18141134488')
    contact_other_info=wait.until(lambda x:x.find_element_by_xpath("//textarea"))
    contact_other_info.send_keys('my wife')
    contact_save_button=wait.until(lambda x:x.find_element_by_xpath("//span[.='确 定']"))
    contact_save_button.click()

except TimeoutException, e:
    # 捕获TimeoutException异常
    print traceback.print_exc()

except NoSuchElementException, e:
    # 捕获NoSuchElementException异常
    print traceback.print_exc()

except Exception, e:
    #Catch other exceptions
    print traceback.print_exc()

result: logging in and adding contacts are ok
C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript.py

Process finished with exit code 0

At this point, the first step has been implemented. Next, let’s look at how to separate the program and data in this program.
Let’s take a look at the main functions of the program:

Log in to your email-->Open the contact page-->Click the Add Contact button-->Enter the contact information in the pop-up window-->Click the Save button.

There is also the core of data-driven --> separation of data and programs

First of all, the steps of logging in to the mailbox can be extracted and packaged independently. The login module is tentatively designated.

Next, we will encapsulate the login function and call it in the program.

Step 2—Extract the login function, encapsulate it, and call it in the main program
Create a new PageObject package under the project
Create a new python file of LoginPage under the PageObject package to encapsulate the login operation.
Code:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

class LoginPage(object):

    def __init__(self,driver):

        self.driver=driver

    def login(self):

        try:

            wait = WebDriverWait(driver, 10, 0.2) # Display waiting

            self.driver.switch_to.frame(self.driver.find_element_by_xpath("//iframe[@id='x-URS-iframe']")) # Switch to the frame element where the username and password input boxes are located

            name = wait.until(lambda x: x.find_element_by_xpath("//input[@placeholder='Email account or mobile phone number' and @name='email']"))

            name.send_keys('xiaxiaoxu1987')

            password = wait.until(lambda x: x.find_element_by_xpath("//input[@placeholder='密码']"))

            password.send_keys('gloryroad')

            submit = wait.until(lambda x: x.find_element_by_xpath("//a[@id='dologin']"))

            submit.click()

            self.driver.switch_to.default_content() # If you use switch_to_default_content() in pycharm, it will be strikethrough and out.

            time.sleep(5)

            assert u"退出" in self.driver.page_source, "no exist in page_source"

        except TimeoutException, e:

            #Catch TimeoutException exception

            print traceback.print_exc()

        except NoSuchElementException, e:

            #Catch NoSuchElementException exception

            print traceback.print_exc()

        except Exception, e:

            #Catch other exceptions

            print traceback.print_exc()

if __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    login=LoginPage(driver)

    login.login()

Result: Login successful

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/Login_page.py

Process finished with exit code 0

At this point, the login function is encapsulated. Next, modify the main program and call LoginPage.
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

lp=LoginPage(driver)

wait = WebDriverWait(driver, 10, 0.2) # Display waiting

try:

    lp.login()

    address_book_link=wait.until(lambda x:x.find_element_by_xpath("//div[text()='通讯录']"))

    address_book_link.click()

    #assert u"New Contact" in driver.page_source

    add_contact_button=wait.until(lambda x:x.find_element_by_xpath("//span[text()='New Contact']"))

    add_contact_button.click()

    contact_name=wait.until(lambda x:x.find_element_by_xpath("//a[@title='Edit detailed name']/preceding-sibling::div/input"))

    contact_name.send_keys(u"徐凤钗")

    contact_email=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_MAIL_wrap']//input"))

    contact_email.send_keys("[email protected]")

    contact_is_star=wait.until(lambda x:x.find_element_by_xpath("//span[text()='Set as star contact']/preceding-sibling::span/b"))

    contact_is_star.click()

    contact_mobile=wait.until(lambda x:x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input"))

    contact_mobile.send_keys('18141134488')

    contact_other_info=wait.until(lambda x:x.find_element_by_xpath("//textarea"))

    contact_other_info.send_keys('my wife')

    contact_save_button=wait.until(lambda x:x.find_element_by_xpath("//span[.='确 定']"))

    contact_save_button.click()

except TimeoutException, e:

    #Catch TimeoutException exception

    print traceback.print_exc()

except NoSuchElementException, e:

    #Catch NoSuchElementException exception

    print traceback.print_exc()

except Exception, e:

    #Catch other exceptions

    print traceback.print_exc()

Result: Success

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Process finished with exit code 0

From the perspective of the main program, the action of adding contacts can also be encapsulated. Let’s encapsulate this part first. If there are any problems later, we can go back and deduce it. First do it according to this idea, and then do it again.

Step 3—Encapsulate the function of adding contacts
Create a new AddressBook python file under the PageObject package
CodeAddressBook.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

class AddressBook(object):

    def __init__(self,driver):

        self.driver=driver

    def add_contact(self):

        try:

            wait = WebDriverWait(self.driver, 10, 0.2) # Display waiting

            address_book_link = wait.until(lambda x: x.find_element_by_xpath("//div[text()='通讯录']"))

            address_book_link.click()

            # assert u"New Contact" in driver.page_source

            add_contact_button = wait.until(lambda x: x.find_element_by_xpath("//span[text()='New Contact']"))

            add_contact_button.click()

            contact_name = wait.until(

                lambda x: x.find_element_by_xpath("//a[@title='Edit detailed name']/preceding-sibling::div/input"))

            contact_name.send_keys(u"徐凤钗")

            contact_email = wait.until(lambda x: x.find_element_by_xpath("//*[@id='iaddress_MAIL_wrap']//input"))

            contact_email.send_keys("[email protected]")

            contact_is_star = wait.until(

                lambda x: x.find_element_by_xpath("//span[text()='Set as star contact']/preceding-sibling::span/b"))

            contact_is_star.click()

            contact_mobile = wait.until(lambda x: x.find_element_by_xpath("//*[@id='iaddress_TEL_wrap']//dd//input"))

            contact_mobile.send_keys('18141134488')

            contact_other_info = wait.until(lambda x: x.find_element_by_xpath("//textarea"))

            contact_other_info.send_keys('my wife')

            contact_save_button = wait.until(lambda x: x.find_element_by_xpath("//span[.='确 定']"))

            contact_save_button.click()

        except TimeoutException, e:

            #Catch TimeoutException exception

            print traceback.print_exc()

        except NoSuchElementException, e:

            #Catch NoSuchElementException exception

            print traceback.print_exc()

        except Exception, e:

            #Catch other exceptions

            print traceback.print_exc()

if __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get('http://mail.126.com')

    lp=LoginPage(driver)

    lp.login()

    ab=AddressBook(driver)

    ab.add_contact()

Result: Success

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/AddressBook.py

Process finished with exit code 0

At this point, the function of adding contacts is roughly encapsulated. Now call it in the main program.
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from PageObject.AddressBook import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

loginPage=LoginPage(driver)

addressBook=AddressBook(driver)

loginPage.login()

addressBook.add_contact()

Result: Success

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Process finished with exit code 0

At this point, the two functions of the program - logging in and adding contacts - have been roughly encapsulated. You can directly call the function in the main program. Let's review the main functions of the program:

Log in to your email-->Open the contact page-->Click the Add Contact button-->Enter the contact information in the pop-up window-->Click the Save button. There is also the core of data-driven --> separation of data and programs

Next, I want to try to extract part of the data. Let’s see how to separate this data?

From the perspective of the program, the part that calls the data is in the two modules just encapsulated, Login_Page and AddressBook. Let’s see how the program uses the data.

Login_page:

AddressBook:

When encapsulating these two functions, no parameters are left out, and they are written directly in the function. This is obviously relatively low, so how to do it? Let's try to replace the data that needs to be called in the function with parameters, and then pass the parameters in when calling.

Let’s first modify the login function and see how to change it to use parameters. At this time, I suddenly became confused. With so many different data, there is no way to use parameters. . .

If you want to use parameter transfer, you need to split the login function. You can see that there are several parts of the login function that can be encapsulated. For example, find the function of the frame element, find the function of the username input box element, and then find the single In the function of the element, you can pass data to the parameters for search.

Step 4—Encapsulate the function of finding elements
Modify LoginPage.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

class LoginPage(object):

    def __init__(self,driver):

        self.driver=driver

        self.wait = WebDriverWait(self.driver, 10, 0.2) # Show waiting

    def getFrame(self,locateType,locateExpression):

        frame=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//iframe[@id='x-URS-iframe']"

        return frame

    def getUserName(self,locateType,locateExpression):

        userName=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='Email account or mobile phone number' and @name='email']"

        return userName

    def getPassword(self,locateType,locateExpression):

        password=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='密码']"

        return password

    def getLoginButton(self,locateType,locateExpression):

        loginButton=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//a[@id='dologin']"

        return loginButton

if __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp=LoginPage(driver)

    driver.switch_to.frame(lp.getFrame("xpath","//iframe[@id='x-URS-iframe']"))

    time.sleep(2)

    lp.getUserName("xpath","//input[@placeholder='email account or mobile phone number' and @name='email']").clear()

    lp.getUserName("xpath","//input[@placeholder='email account or mobile phone number' and @name='email']").send_keys("xiaxiaoxu1987")

    lp.getPassword("xpath","//input[@placeholder='密码']").send_keys("gloryroad")

    lp.getLoginButton("xpath","//a[@id='dologin']").click()

    driver.switch_to.default_content()

    time.sleep(5)

    assert u"退出" in driver.page_source, "no exist in page_source"

Result: Login successful
At this point, although the data is passed as a parameter to each function that finds elements, there is a problem.

When calling, you need to manually enter the data needed to find the element, which is more troublesome. If you enter a wrong letter, the element will not be found. How to do this?

It needs to be re-encapsulated, put the data in a file, and then encapsulate the method to read the data from the file. In this way, you need to create a configuration file to store the data, and then create a new python file to encapsulate the method of reading the configuration file.

Step 5—Put the data into the configuration file, and then encapsulate the method to read the data from the file
Create a new package called Conf under the project (used to store configuration-related files):
Create a new file under the Conf package: PageObjectRepository.ini

PageObjectRepository.ini

[126mail_login]

login_page.frame=id>x-URS-iframe

login_page.username=xpath>//input[@name='email']

login_page.password=xpath>//input[@name='password']

login_page.loginbutton=id>dologin

[126mail_homepage]

home_page.addressbook=xpath>//div[text()='Address Book']

[126mail_addcontactspage]

addcontacts_page.createcontactsbtn=xpath>//span[text()='New Contact']

addcontacts_page.contactpersonname=xpath>//a[@title='Edit detailed name']/preceding-sibling::div/input

addcontacts_page.contactpersonemail=xpath>//*[@id='iaddress_MAIL_wrap']//input

addcontacts_page.starcontacts=xpath>//span[text()='Set as star contact']/preceding-sibling::span/b

addcontacts_page.contactpersonmobile=xpath>//*[@id='iaddress_TEL_wrap']//dd//input

addcontacts_page.contactpersoncomment=xpath>//textarea

addcontacts_page.savecontaceperson=xpath>//span[.='OK']

Create a new Util package under the project. This package is generally used to store tool classes, such as reading configuration files, finding element methods, excel operation classes, time classes, log methods and operations, screenshots, report templates, etc.
Create a new python file under the Util package: ParsePageObjectRepository.py to encapsulate the class for reading configuration files

#encoding=utf-8

#author-Xia Xiaoxu

from ConfigParser import ConfigParser

class ParsePageObjectRepositoryConfig(object):

    def __init__(self,config_path):

        self.cf=ConfigParser()#Generate parser

        self.cf.read(config_path)

    def getItemSection(self,sectionName):

        print self.cf.items(sectionName)

        return dict(self.cf.items(sectionName))

    def getOptionValue(self,sectionName,optionName):#Return a dictionary

        print self.cf.get(sectionName,optionName)

        return self.cf.get(sectionName,optionName)

if __name__=='__main__':

    pp=ParsePageObjectRepositoryConfig("D:\\test\\dataDrivenTestPractice1\\Conf\\PageObjectRepository.ini")

    print pp.getItemSection("126mail_login")

print pp.getOptionValue("126mail_login","login_page.username")

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ParsePageObjectRepository.py

[('login_page.frame', 'id>x-URS-iframe'), ('login_page.username', "xpath>//input[@name='email']"), ('login_page.password', "xpath>//input[@name='password']"), ('login_page.loginbutton', 'id>dologin')]

{'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

xpath>//input[@name='email']

xpath>//input[@name='email']

Process finished with exit code 0

You can see that when the read function is called in the test code, the path to the configuration file must be manually entered in the parameter. It is a long character. If the path is modified, it needs to be modified here. Since it is all encapsulated here, it is easy to modify it here. Be diligent and configure the path in a variable.

Generally, the variable storing the file path should be placed in the var.py file under the ProjectVar package. After that, the paths of all configuration files are maintained in the form of variables in this file. The relative path is used to obtain the path, which is more secure.

Step 6—Use variables to store the path to the configuration file
Create a new ProjectVar package under the project
Create a new python file of var.py under the ProjectVar package
var.py:

#encoding=utf-8

#author-Xia Xiaoxu

import us

#Get the absolute path of the directory where the project is located

project_path=os.path.dirname(os.path.dirname(__file__))

#Get the absolute path of the page object library file

page_object_repository_path=project_path.decode("utf-8")+u"/conf/PageObjectRepository.ini"

if __name__=='__main__':

    #Test code

    print "project_path:", project_path

    print "page_object_repository_path:",page_object_repository_path

    print os.path.exists(project_path)

    print os.path.exists(page_object_repository_path)

result:

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/ProjectVar/var.py

project_path: D:/test/dataDrivenTestPractice1

page_object_repository_path: D:/test/dataDrivenTestPractice1/conf/PageObjectRepository.ini

True

True

Process finished with exit code 0

Now test the execution of reading the configuration file in ParsePageObjectRepository.py

ParsePageObjectRepository.py:

#encoding=utf-8

#author-Xia Xiaoxu

from ConfigParser import ConfigParser

from ProjectVar.var import page_object_repository_path#Newly added

class ParsePageObjectRepositoryConfig(object):

    def __init__(self):#Removed the config_path parameter

        self.cf=ConfigParser()#Generate parser

        self.cf.read(page_object_repository_path)#Replace directly with variables

    def getItemSection(self,sectionName):

        print self.cf.items(sectionName)

        return dict(self.cf.items(sectionName))

    def getOptionValue(self,sectionName,optionName):#Return a dictionary

        print self.cf.get(sectionName,optionName)

        return self.cf.get(sectionName,optionName)

if __name__=='__main__':

    pp=ParsePageObjectRepositoryConfig()#The address variable of the configuration file has been initialized in the constructor

    print pp.getItemSection("126mail_login")

print pp.getOptionValue("126mail_login","login_page.username")

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ParsePageObjectRepository.py

[('login_page.frame', 'id>x-URS-iframe'), ('login_page.username', "xpath>//input[@name='email']"), ('login_page.password', "xpath>//input[@name='password']"), ('login_page.loginbutton', 'id>dologin')]

{'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

xpath>//input[@name='email']

xpath>//input[@name='email']

Next, fix the calls in the login.py file and replace all the parameters that need to be entered manually with reading the configuration file.
Modify login.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from Util.ParsePageObjectRepository import *#新加

from ProjectVar.var import *# Newly added

class LoginPage(object):

    def __init__(self,driver):

        self.driver=driver

        self.parse_config_file=ParsePageObjectRepositoryConfig()# Newly added, obtain configuration file information

        self.login_page_items=self.parse_config_file.getItemSection("126mail_login")#新加

        print "self.login_page_items:",self.login_page_items

        self.wait = WebDriverWait(self.driver, 10, 0.2) # Show waiting

    def getFrame(self):#Remove the parameters and process them inside

        locateType,locateExpression=self.login_page_items['login_page.frame'].split('>')#id>x-URS-iframe

        frame=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//iframe[@id='x-URS-iframe']"

        return frame

    def getUserName(self): #Remove the parameters and process them inside

        locateType, locateExpression = self.login_page_items['login_page.username'].split('>')#xpath>//input[@name='email']

        userName=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='Email account or mobile phone number' and @name='email']"

        return userName

    def getPassword(self): #Remove the parameters and process them inside

        locateType, locateExpression = self.login_page_items['login_page.password'].split('>')#xpath>//input[@name='password']

        password=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//input[@placeholder='密码']"

        return password

    def getLoginButton(self): #Remove the parameters and process them inside

        locateType, locateExpression = self.login_page_items['login_page.loginbutton'].split('>') #id>dologin

        loginButton=self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression))#"//a[@id='dologin']"

        return loginButton

if __name__=="__main__":

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp=LoginPage(driver)

    driver.switch_to.frame(lp.getFrame())

    time.sleep(2)

    lp.getUserName().clear()

    lp.getUserName().send_keys("xiaxiaoxu1987")

    lp.getPassword().send_keys("gloryroad")

    lp.getLoginButton().click()

    driver.switch_to.default_content()

    time.sleep(5)

assert u"退出" in driver.page_source, "no exist in page_source"

So far, we have encapsulated a lot of things and put the login data in the configuration file to read it. However, there is still a long way to go before perfection, but it doesn’t matter. As long as we have a clear idea, perfection is only a matter of time. Now let’s Let’s see if there are any problems with this framework that need to be optimized.
You can see that the following two points can be optimized:

1-In the method of obtaining login page elements in the login_page.py file, the following steps for finding elements can be encapsulated,

self.wait.until(lambda x: x.find_element(by=locateType,value=locateExpression)), there is no need to write this in every method of finding elements, and this step of finding elements is in the process of adding contacts to the account It will also be used in functions. It will be much more convenient to encapsulate the method of finding elements.

2-Secondly, when performing the login operation, we enter the username and password information manually. This can also be encapsulated. How to encapsulate it? Each method in the initial login.py file gets the login information. For the required elements, we manually call these methods when performing the login operation. After obtaining the elements, enter characters or click to complete the login operation. Then these steps can be performed in another file. Encapsulation, to put it bluntly, is to encapsulate the methods of obtaining each element in login_page to realize the login function. You don’t need to organize the scattered methods by yourself every time. Put it in a box. The name of the box is login. Every time Just execute this box, don't worry about the details inside, all packaging is the same.

Step 7—Encapsulate the function of finding elements and further encapsulate the login function

As you can see in the initial frame structure, the method of finding elements can be placed in the Util package

Create a new ObjectMap.py file in the Util package
ObjectMap.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium.webdriver.support.ui import WebDriverWait

#Get a single element object

def getElement(driver,locateType,locateExpression):

    try:

        element=WebDriverWait(driver,10).until(lambda x:x.find_element(by=locateType,value=locateExpression))

        return element

    except Exception,e:

        raise e

#Get multiple identical page element objects and return them as a list

def getElements(driver,locateType,locatorExpression):

    try:

        elements=WebDriverWait(driver,5).until(lambda x:x.find_elements(by=locateType,value=locateExpression))

        return elements

    except Exception,e:

        raise e

if __name__=="__main__":

    #Test code

    from selenium import webdriver

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get('http://www.baidu.com')

    searchBox=getElement(driver,"xpath","//input[@id='kw']")

    driver.quit()

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/ObjectMap.py

Process finished with exit code 0

At this point, the method of finding elements is encapsulated. Let’s modify Login_Page.py to call the ObjectMap method to implement each method of finding elements, and encapsulate the login action.
Login_page.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from Util.ParsePageObjectRepository import *

from ProjectVar.var import *

from Util.ObjectMap import *

class LoginPage(object):

    def __init__(self,driver):

        self.driver=driver

        self.parse_config_file=ParsePageObjectRepositoryConfig()

        self.login_page_items=self.parse_config_file.getItemSection("126mail_login")

        print "self.login_page_items:",self.login_page_items

        self.wait = WebDriverWait(self.driver, 10, 0.2) # Show waiting

    def getFrame(self):

        locateType,locateExpression=self.login_page_items['login_page.frame'].split('>')#id>x-URS-iframe

        frame=getElement(self.driver,locateType,locateExpression)#"//iframe[@id='x-URS-iframe']"

        return frame

    def getUserName(self):

        locateType, locateExpression = self.login_page_items['login_page.username'].split('>')#xpath>//input[@name='email']

        userName=getElement(self.driver,locateType,locateExpression)#"//input[@placeholder='Email account or mobile phone number' and @name='email']"

        return userName

    def getPassword(self):

        locateType, locateExpression = self.login_page_items['login_page.password'].split('>')#xpath>//input[@name='password']

        password=getElement(self.driver,locateType,locateExpression)#"//input[@placeholder='密码']"

        return password

    def getLoginButton(self):

        locateType, locateExpression = self.login_page_items['login_page.loginbutton'].split('>') #id>dologin

        loginButton=getElement(self.driver,locateType,locateExpression)#"//a[@id='dologin']"

        return loginButton

    def login(self):

        self.driver.switch_to.frame(self.getFrame())

        self.getUserName().clear()

        self.getUserName().send_keys("xiaxiaoxu1987")

        self.getPassword().send_keys("gloryroad")

        self.getLoginButton().click()

if __name__=="__main__":

    #Test code

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http:\\mail.126.com")

    lp=LoginPage(driver)

lp.login()

Result: Can log in

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/Login_Page.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

Process finished with exit code 0

Next, we move the login function package out of Login_page.py and store it as a separate file to separate the methods and calls. If there are changes in the future, just modify login_page.py.

Step 8—Encapsulate the login method separately
Create a new Action package under the project
Create a new login.py under the Action package
Login.py:

#encoding=utf-8

#author-Xia Xiaoxu

from PageObject.Login_Page import *

from selenium import webdriver

def login(driver,username,password):

    lp=LoginPage(driver)

    driver.switch_to.frame(lp.getFrame())

    lp.getUserName().clear()

    lp.getUserName().send_keys(username)

    lp.getPassword().send_keys(password)

    lp.getLoginButton().click()

if __name__=='__main__':

    #Test code

    driver=webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http://mail.126.com")

    login(driver,"xiaxiaoxu1987","gloryroad")

Result: Login successful

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/login.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

Process finished with exit code 0

At this point, the login function is basically encapsulated, and the data and program are separated. Let's take a look at the encapsulation of adding contacts to realize the separation of data and program step by step. The operations of adding contacts have been put into AddressBook.py before. , but the situation is the same as the login_page.py at the beginning. The element search operation and configuration file data reading have not been done yet. Let’s start doing this.
Step 9—Encapsulate the add contact operation
Idea:

In AddressBook.py, encapsulate each element needed to add a contact page into a method, find the xpath data required for each element and put it in the configuration file, and then use a function to call the methods of these elements to implement input characters or click operations. Implement the function of adding contacts

AddressBook.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from Action.login import *

class AddressBook(object):

    def __init__(self,driver):

        self.driver=driver

        self.parse_config_file=ParsePageObjectRepositoryConfig()

        self.address_book_page=self.parse_config_file.getItemsFromSection("126mail_homepage")

        print "self.address_book_page:",self.address_book_page

        self.address_book_page_itmes=self.parse_config_file.getItemsFromSection("126mail_addcontactspage")

        print "self.address_book_page_itmes:", self.address_book_page_itmes

    def address_book_link(self):

        locateType,locateExpression = self.address_book_page['home_page.addressbook'].split(">")

        print locateType,locateExpression

        return getElement(self.driver,"xpath","//div[text()='Address Book']")

    def add_contact_button(self):

        locateType,locateExpression=self.address_book_page_itmes['addcontacts_page.createcontactsbtn'].split(">")

        print locateType,locateExpression

        return getElement(self.driver,locateType,locateExpression)

    def contact_name(self):

        locateType,locateExpression=self.address_book_page_itmes['addcontacts_page.contactpersonname'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

    def contact_email(self):

        locateType, locateExpression = self.address_book_page_itmes['addcontacts_page.contactpersonemail'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

    def contact_is_star(self):

        locateType, locateExpression = self.address_book_page_itmes['addcontacts_page.starcontacts'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

    def contact_mobile(self):

        locateType, locateExpression = self.address_book_page_itmes['addcontacts_page.contactpersonmobile'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

    def contact_other_info(self):

        locateType, locateExpression = self.address_book_page_itmes['addcontacts_page.contactpersoncomment'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

    def contact_save_button(self):

        locateType, locateExpression = self.address_book_page_itmes['addcontacts_page.savecontaceperson'].split(">")

        print locateType, locateExpression

        return getElement(self.driver, locateType, locateExpression)

if __name__=="__main__":

    driver = webdriver.Firefox(executable_path='c:\\geckodriver')

    driver.get("http://mail.126.com")

    login(driver, "xiaxiaoxu1987", "gloryroad")

    addressbook=AddressBook(driver)

    time.sleep(5)

    addressbook.address_book_link().click()

    addressbook.add_contact_button().click()

    addressbook.contact_name().send_keys("sam")

    addressbook.contact_email().send_keys("[email protected]")

    addressbook.contact_is_star().click()

    addressbook.contact_mobile().send_keys("18142244444")

    addressbook.contact_other_info().send_keys("myself")

addressbook.contact_save_button().click()

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/PageObject/AddressBook.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

self.address_book_page: {'home_page.addressbook': "xpath>//div[text()='\xe9\x80\x9a\xe8\xae\xaf\xe5\xbd\x95']"}

self.address_book_page_itmes: {'addcontacts_page.createcontactsbtn': "xpath>//span[text()='\xe6\x96\xb0\xe5\xbb\xba\xe8\x81\x94\xe7\xb3\xbb\xe4\xba\xba']", 'addcontacts_page.contactpersonmobile': "xpath>//*[@id='iaddress_TEL_wrap']//dd//input", 'addcontacts_page.contactpersonemail': "xpath>//*[@id='iaddress_MAIL_wrap']//input", 'addcontacts_page.contactpersoncomment': 'xpath>//textarea', 'addcontacts_page.contactpersonname': "xpath>//a[@title='\xe7\xbc\x96\xe8\xbe\x91\xe8\xaf\xa6\xe7\xbb\x86\xe5\xa7\x93\xe5\x90\x8d']/preceding-sibling::div/input", 'addcontacts_page.savecontaceperson': "xpath>//span[.='\xe7\xa1\xae \xe5\xae\x9a']", 'addcontacts_page.starcontacts': "xpath>//span[text()='\xe8\xae\xbe\xe4\xb8\xba\xe6\x98\x9f\xe6\xa0\x87\xe8\x81\x94\xe7\xb3\xbb\xe4\xba\xba']/preceding-sibling::span/b"}

xpath //div[text()='Address Book']

xpath //span[text()='New Contact']

xpath //a[@title='Edit detailed name']/preceding-sibling::div/input

xpath //*[@id='iaddress_MAIL_wrap']//input

xpath //span[text()='Set as star contact']/preceding-sibling::span/b

xpath //*[@id='iaddress_TEL_wrap']//dd//input

xpath //textarea

xpath //span[.='OK']

Now, we have encapsulated the operation of adding each element of the contact page and called it in the test code. Just like the encapsulation of the login function, we have encapsulated the operation of adding each element of the contact page in another file. , just call it directly in the main program, which is convenient for operation.
Step 10—Separately encapsulate the add contact function of addressBook
Create a new add_contact.py file under the Action package
add_contact.py:

#encoding=utf-8

#author-Xia Xiaoxu

from PageObject.AddressBook import *

from selenium import webdriver

def add_contact(driver):

    driver.switch_to.default_content()

    addressbook = AddressBook(driver)

    addressbook.address_book_link().click()

    addressbook.add_contact_button().click()

    addressbook.contact_name().send_keys("sam")

    addressbook.contact_email().send_keys("[email protected]")

    addressbook.contact_is_star().click()

    addressbook.contact_mobile().send_keys("18142244444")

    addressbook.contact_other_info().send_keys("myself")

    addressbook.contact_save_button().click()

if __name__=='__main__':

    driver=webdriver.Firefox(executable_path="c:\\geckodriver")

    driver.get("http://mail.126.com")

    login(driver, "xiaxiaoxu1987", "gloryroad")

    add_contact(driver)

   

result:

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/add_contact.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

Process finished with exit code 0

Further encapsulate, replace the input part with parameters

#encoding=utf-8

#author-Xia Xiaoxu

from PageObject.AddressBook import *

from selenium import webdriver

def add_contact(driver,name="",email="",is_star=True,mobile="",otherinfo=""):

    driver.switch_to.default_content()

    addressbook = AddressBook(driver)

    addressbook.address_book_link().click()

    addressbook.add_contact_button().click()

    addressbook.contact_name().send_keys(name)

    addressbook.contact_email().send_keys(email)

    if is_star==True:

        addressbook.contact_is_star().click()

    addressbook.contact_mobile().send_keys(mobile)

    addressbook.contact_other_info().send_keys(otherinfo)

    addressbook.contact_save_button().click()

if __name__=='__main__':

    driver=webdriver.Firefox(executable_path="c:\\geckodriver")

    driver.get("http://mail.126.com")

    login(driver, "xiaxiaoxu1987", "gloryroad")

    add_contact(driver,"xiaxiaoxu","[email protected]",True,"13333334444","gloryroad")

driver.quit()

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Action/add_contact.py

self.login_page_items: {'login_page.loginbutton': 'id>dologin', 'login_page.username': "xpath>//input[@name='email']", 'login_page.frame': 'id>x-URS-iframe', 'login_page.password': "xpath>//input[@name='password']"}

Process finished with exit code 0

At this point, we have encapsulated most of the functions. Now let’s try calling these functions in the main program:
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from PageObject.AddressBook import *

from Action.add_contact import *

from Action.login import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

login(driver, "xiaxiaoxu1987", "gloryroad")

add_contact(driver,"xiaxiaoxu","[email protected]",True,"13333334444","gloryroad")

driver.quit()

Result: It works fine.

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

Process finished with exit code 0

Judging from the calls in the main program, there are still some data that need to be entered manually, such as user names, passwords, and contact information that need to be added. If you need to add multiple contacts, you need to enter it multiple times. Next step Let’s look at how to separate this part of the data from the program and save it in a file. This time we will put it in Excel, and then use the method of operating Excel to extract the data.
Step 11-Encapsulate excel operations
Create an excel file and put the 126 account information in the first sheet.

The second sheet contains contacts:

Create a new TestData package under the project and put the excel file under the package.
Excel.py:

#encoding=utf-8

#author-Xia Xiaoxu

# encoding=utf-8

from openpyxl import load_workbook

from openpyxl.styles import Border, Side, Font

import time

from ProjectVar.var import *

class parseExcel(object):

    def __init__(self, excelPath):

        self.excelPath = excelPath

        self.workbook = load_workbook(excelPath)  # 加载excel

        self.sheet = self.workbook.active # Get the first sheet

        self.font = Font(color=None)

        self.colorDict = {"red": 'FFFF3030', "green": 'FF008B00'}

    #Set the sheet object currently to be operated and use index to get the corresponding sheet

    def set_sheet_by_index(self, sheet_index):

        sheet_name = self.workbook.get_sheet_names()[sheet_index]

        self.sheet = self.workbook.get_sheet_by_name(sheet_name)

        return self.sheet

    # Get the name of the current default sheet

    def get_default_sheet(self):

        return self.sheet.title

    #Set the sheet object currently to be operated and use the sheet name to get the corresponding sheet

    def set_sheet_by_name(self, sheet_name):

        sheet = self.workbook.get_sheet_by_name(sheet_name)

        self.sheet = sheet

        return self.sheet

    # Get the maximum number of rows in the default sheet

    def get_max_row_no(self):

        return self.sheet.max_row

    # Get the maximum number of columns of the default sheet

    def get_max_col_no(self):

        return self.sheet.max_column

    # Get the minimum (starting) row number of the default sheet

    def get_min_row_no(self):

        return self.sheet.min_row

    # Get the minimum (starting) column number of the default sheet

    def get_min_col_no(self):

        return self.sheet.min_column

    # Get all row objects of the default sheet,

    def get_all_rows(self):

        return list(self.sheet.iter_rows())

        # return list(self.rows) can also be used

    # Get all column objects in the default sheet

    def get_all_cols(self):

        return list(self.sheet.iter_cols())

        # return list(self.sheet.columns) can also be used

    # Get a column from the default sheet, the first column starts from 0

    def get_single_col(self, col_no):

        return self.get_all_cols()[col_no]

    # Get a certain row from the default sheet, the first row starts from 0

    def get_single_row(self, row_no):

        return self.get_all_rows()[row_no]

    # From the default sheet, obtain the specified cell through the row number and column number. Note that the row number and column number start from 1

    def get_cell(self, row_no, col_no):

        return self.sheet.cell(row=row_no, column=col_no)

    # From the default sheet, obtain the contents of the specified cell through the row number and column number. Note that the row number and column number start from 1

    def get_cell_content(self, row_no, col_no):

        return self.sheet.cell(row=row_no, column=col_no).value

    # From the default sheet, write the specified content into the specified cell through the row number and column number. Note that the row number and column number start from 1

    # When calling this method, excel should not be open.

    def write_cell_content(self, row_no, col_no, content, font=None):

        self.sheet.cell(row=row_no, column=col_no).value = content

        self.workbook.save(self.excelPath)

        return self.sheet.cell(row=row_no, column=col_no).value

    # From the default sheet, write the current date into the specified cell through the row number and column number. Note that the row number and column number start from 1

    # When calling this method, excel should not be open.

    def write_cell_current_time(self, row_no, col_no):

        time1 = time.strftime("%Y-%m-%d %H:%M:%S")

        self.sheet.cell(row=row_no, column=col_no).value = str(time1)

        self.workbook.save(self.excelPath)

        return self.sheet.cell(row=row_no, column=col_no).value

    def save_excel_file(self):

        self.workbook.save(self.excelPath)

if __name__ == '__main__':

    #Test code

    p = parseExcel(test_data_excel_path)

    print u"Get default sheet:", p.get_default_sheet()

    print u"Set sheet index to 1", p.set_sheet_by_index(1)

    print u"Get default sheet:", p.get_default_sheet()

    print u"Set sheet index to 0", p.set_sheet_by_index(0)

    print u"Get default sheet:", p.get_default_sheet()

    print u"Maximum number of rows:", p.get_max_row_no()

    print u"Maximum number of columns:", p.get_max_col_no()

    print u"Minimum starting row number:", p.get_min_row_no()

    print u"Minimum starting number of columns:", p.get_min_col_no()

    print u"All row objects:", p.get_all_rows()

    print u"All column objects:", p.get_all_cols()

    print u"Get a certain column (2):", p.get_single_col(2)

    print u"Get a certain row(1):", p.get_single_row(1)

    print u"Get row number and column number (2,2) cell:", p.get_cell(2, 2)

    print u"Get the contents of the row number and column number cell (2, 2)", p.get_cell_content(2, 2)

    print u"row and column number write content (11,11): 'xiaxiaoxu'", p.write_cell_content(11, 11, 'xiaxiaoxu') #

    print u"The row number and column number are written into the current date (13,13):", p.write_cell_current_time(13, 13)

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/Excel.py

Get the default sheet: Contact

Set sheet index to 1 <Worksheet "\u8054\u7cfb\u4eba">

Get the default sheet: Contact

Set sheet index to 0 <Worksheet "126\u8d26\u53f7">

Get the default sheet: 126 account

Maximum number of rows: 3

Maximum number of columns: 6

Minimum number of starting lines: 1

Minimum number of starting columns: 1

所有行对象: [(<Cell u'126\u8d26\u53f7'.A1>, <Cell u'126\u8d26\u53f7'.B1>, <Cell u'126\u8d26\u53f7'.C1>, <Cell u'126\u8d26\u53f7'.D1>, <Cell u'126\u8d26\u53f7'.E1>, <Cell u'126\u8d26\u53f7'.F1>), (<Cell u'126\u8d26\u53f7'.A2>, <Cell u'126\u8d26\u53f7'.B2>, <Cell u'126\u8d26\u53f7'.C2>, <Cell u'126\u8d26\u53f7'.D2>, <Cell u'126\u8d26\u53f7'.E2>, <Cell u'126\u8d26\u53f7'.F2>), (<Cell u'126\u8d26\u53f7'.A3>, <Cell u'126\u8d26\u53f7'.B3>, <Cell u'126\u8d26\u53f7'.C3>, <Cell u'126\u8d26\u53f7'.D3>, <Cell u'126\u8d26\u53f7'.E3>, <Cell u'126\u8d26\u53f7'.F3>)]

所有列对象: [(<Cell u'126\u8d26\u53f7'.A1>, <Cell u'126\u8d26\u53f7'.A2>, <Cell u'126\u8d26\u53f7'.A3>), (<Cell u'126\u8d26\u53f7'.B1>, <Cell u'126\u8d26\u53f7'.B2>, <Cell u'126\u8d26\u53f7'.B3>), (<Cell u'126\u8d26\u53f7'.C1>, <Cell u'126\u8d26\u53f7'.C2>, <Cell u'126\u8d26\u53f7'.C3>), (<Cell u'126\u8d26\u53f7'.D1>, <Cell u'126\u8d26\u53f7'.D2>, <Cell u'126\u8d26\u53f7'.D3>), (<Cell u'126\u8d26\u53f7'.E1>, <Cell u'126\u8d26\u53f7'.E2>, <Cell u'126\u8d26\u53f7'.E3>), (<Cell u'126\u8d26\u53f7'.F1>, <Cell u'126\u8d26\u53f7'.F2>, <Cell u'126\u8d26\u53f7'.F3>)]

Get a certain column (2): (<Cell u'126\u8d26\u53f7'.C1>, <Cell u'126\u8d26\u53f7'.C2>, <Cell u'126\u8d26\u53f7'.C3>)

获取某一行(1): (<Cell u'126\u8d26\u53f7'.A2>, <Cell u'126\u8d26\u53f7'.B2>, <Cell u'126\u8d26\u53f7'.C2>, <Cell u'126\u8d26\u53f7'.D2>, <Cell u'126\u8d26\u53f7'.E2>, <Cell u'126\u8d26\u53f7'.F2>)

Get the row number and column number (2,2) cell: <Cell u'126\u8d26\u53f7'.B2>

Get the contents of row number and column number cells (2,2) xiaxiaoxu1987

Row number and column number write content (11,11): 'xiaxiaoxu' xiaxiaoxu

The row number and column number are written into the current date (13,13): 2018-07-10 21:28:14

Process finished with exit code 0

At this point, the excel operation has been encapsulated. Let’s try reading the data in the main program.
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from PageObject.AddressBook import *

from Action.add_contact import *

from Action.login import *

from ProjectVar.var import *

from Util.Excel import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"126 account")

print pe.get_default_sheet()

rows=pe.get_all_rows()[1:]

for id,row in enumerate(rows):

    if row[4].value =='y':

        username = row[1].value

        password = row[2].value

        print username, password

        try:

            login(driver,username,password)

            pe.set_sheet_by_name(u"Contact")

            print pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            print "rows1:",rows1

            for id1,row in enumerate(rows1):

                if row[7].value == 'y':

                    try:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        #print "execute1"

                        add_contact(driver,row[1].value,row[2].value,row[3].value,row[4].value,row[5].value)

                        print "assert word:",row[6].value in driver.page_source

                        print row[6].value

                        pe.write_cell_content(id1+2,10,"pass")

                    except Exception,e:

                        print u"Exception message:",e.message

                        pe.write_cell_content(id1+2,10,"fail")

                else:

                    pe.write_cell_content(id1+2,10,u"忽略")

                    continue

        except Exception,e:

            pe.set_sheet_by_name(u"126 account")

            print u"Exception message:",e

            pe.write_cell_content(id+2,5,"fail")

    else:

        pe.set_sheet_by_name(u"126 account")

        pe.write_cell_content(id+2,6,u"忽略")

        continue

Result: execution ok

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126account

xiaxiaoxu1987 gloryroad

Contact person

rows1: [(<Cell u'\u8054\u7cfb\u4eba'.A2>, <Cell u'\u8054\u7cfb\u4eba'.B2>, <Cell u'\u8054\u7cfb\u4eba'.C2>, <Cell u'\u8054\u7cfb\u4eba'.D2>, <Cell u'\u8054\u7cfb\u4eba'.E2>, <Cell u'\u8054\u7cfb\u4eba'.F2>, <Cell u'\u8054\u7cfb\u4eba'.G2>, <Cell u'\u8054\u7cfb\u4eba'.H2>, <Cell u'\u8054\u7cfb\u4eba'.I2>, <Cell u'\u8054\u7cfb\u4eba'.J2>), (<Cell u'\u8054\u7cfb\u4eba'.A3>, <Cell u'\u8054\u7cfb\u4eba'.B3>, <Cell u'\u8054\u7cfb\u4eba'.C3>, <Cell u'\u8054\u7cfb\u4eba'.D3>, <Cell u'\u8054\u7cfb\u4eba'.E3>, <Cell u'\u8054\u7cfb\u4eba'.F3>, <Cell u'\u8054\u7cfb\u4eba'.G3>, <Cell u'\u8054\u7cfb\u4eba'.H3>, <Cell u'\u8054\u7cfb\u4eba'.I3>, <Cell u'\u8054\u7cfb\u4eba'.J3>), (<Cell u'\u8054\u7cfb\u4eba'.A4>, <Cell u'\u8054\u7cfb\u4eba'.B4>, <Cell u'\u8054\u7cfb\u4eba'.C4>, <Cell u'\u8054\u7cfb\u4eba'.D4>, <Cell u'\u8054\u7cfb\u4eba'.E4>, <Cell u'\u8054\u7cfb\u4eba'.F4>, <Cell u'\u8054\u7cfb\u4eba'.G4>, <Cell u'\u8054\u7cfb\u4eba'.H4>, <Cell u'\u8054\u7cfb\u4eba'.I4>, <Cell u'\u8054\u7cfb\u4eba'.J4>), (<Cell u'\u8054\u7cfb\u4eba'.A5>, <Cell u'\u8054\u7cfb\u4eba'.B5>, <Cell u'\u8054\u7cfb\u4eba'.C5>, <Cell u'\u8054\u7cfb\u4eba'.D5>, <Cell u'\u8054\u7cfb\u4eba'.E5>, <Cell u'\u8054\u7cfb\u4eba'.F5>, <Cell u'\u8054\u7cfb\u4eba'.G5>, <Cell u'\u8054\u7cfb\u4eba'.H5>, <Cell u'\u8054\u7cfb\u4eba'.I5>, <Cell u'\u8054\u7cfb\u4eba'.J5>)]

assert word: True

[email protected]

assert word: True

John Doe

Process finished with exit code 0

Excel results:

At this point, most of the functions of the framework have been encapsulated. Next, let’s build the log module so that the program can print logs when executing.

Step 12—Add the log module
Create a new Logger.conf log configuration file under the Conf package, which configures the logger, processor and formatter. The specific details of the log will be listed later.

#logger.conf
###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0

###############################################
[handlers]
keys=hand01,hand02,hand03

[handler_hand01]
class=StreamHandler
level=INFO
formatter=form01
args=(sys.stderr,)

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('DataDrivenFrameWork.log', 'a')

[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form01
args=('DataDrivenFrameWork.log', 'a', 10*1024*1024, 5)

###############################################
[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=%Y-%m-%d %H:%M:%S

Create a new log.py file under the Util package to encapsulate the log operation
Log.py:

#encoding=utf-8

#author-Xia Xiaoxu

import logging

import logging.config

from ProjectVar.var import *

#Read the log configuration file

logging.config.fileConfig(project_path+"\\Conf\\Logger.conf")

#Select a log format

logger=logging.getLogger("example02")

def error(message):

    #Print debug level information

    logger.error(message)

def info(message):

    #Print info level information

    logger.info(message)

def warning(message):

    #Print warning level information

    logger.warning(message)

if __name__=="__main__":

    #Test code

    info("hi")

    print "config file path:",project_path+"\\Conf\\Logger.conf"

    error("world!")

    warning("gloryroad!")

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/log.py

2018-07-11 21:32:12 log.py[line:19] INFO hi

config file path: D:\test\dataDrivenTestPractice1\Conf\Logger.conf

2018-07-11 21:32:12 log.py[line:15] ERROR world!

2018-07-11 21:32:12 log.py[line:23] WARNING gloryroad!

Process finished with exit code 0

The encapsulation of the log is now ok. Let’s modify the main program and call the log.
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from PageObject.AddressBook import *

from Action.add_contact import *

from Action.login import *

from ProjectVar.var import *

from Util.Excel import *

from Util.log import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"126 account")

print pe.get_default_sheet()

rows=pe.get_all_rows()[1:]

for id,row in enumerate(rows):

    if row[4].value =='y':

        username = row[1].value

        password = row[2].value

        print username, password

        try:

            login(driver,username,password)

            pe.set_sheet_by_name(u"Contact")

            print pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            print "rows1:",rows1

            test_data_pass_flag=True#Result representation, used for final writing of excel results

            for id1,row in enumerate(rows1):

                if row[7].value == 'y':

                    try:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        print "log0711",row[1],row[1].value

                        print "log0711",type(row[1].value)

                        #Perform the actual operation of adding contacts

                        add_contact(driver,row[1].value,row[2].value,row[3].value,row[4].value,row[5].value)

                        print "assert word:",row[6].value

                        assert row[6].value in driver.page_source

                        pe.write_cell_content(id1+2,10,"pass")#assert does not report an error, indicating that the assertion is successful

                    except Exception,e:

                        #print u"Exception message 01",e.message

                        pe.write_cell_content(id1+2,10,"fail")

                        test_data_pass_flag=False#The code reaches this point, indicating that there is an exception and the test failed.

                        info(u"Exception message 01" + e.message) #Output log

                else:#The description identifier is 'n', ignore the data

                    pe.write_cell_content(id1+2,10,u"忽略")

                    continue

            if test_data_pass_flag ==True:#If the flag is True, the result is successful

                pe.set_sheet_by_name(u"126 account")

                pe.write_cell_content(id+2,5,"成功")

            else:#Indicates that the flag is False

                pe.set_sheet_by_name(u"126 account")

                pe.write_cell_content(id+2,5,"Failed")

        except Exception,e:

            pe.set_sheet_by_name(u"126 account")

            #print u"Exception message 02:",e

            pe.write_cell_content(id+2,6,"fail")

            info(u"Exception message 02:"+e.message)#Output log

        time.sleep(2)

        driver.quit()

    else:#Take this branch, indicating that the identifier is "n"

        pe.set_sheet_by_name(u"126 account")

        pe.write_cell_content(id+2,6,u"忽略")

        continue

Result: Run OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126account

xiaxiaoxu1987 gloryroad

2018-07-11 22:55:25 log.py[line:19] INFO login successfully

Contact person

rows1: [(<Cell u'\u8054\u7cfb\u4eba'.A2>, <Cell u'\u8054\u7cfb\u4eba'.B2>, <Cell u'\u8054\u7cfb\u4eba'.C2>, <Cell u'\u8054\u7cfb\u4eba'.D2>, <Cell u'\u8054\u7cfb\u4eba'.E2>, <Cell u'\u8054\u7cfb\u4eba'.F2>, <Cell u'\u8054\u7cfb\u4eba'.G2>, <Cell u'\u8054\u7cfb\u4eba'.H2>, <Cell u'\u8054\u7cfb\u4eba'.I2>, <Cell u'\u8054\u7cfb\u4eba'.J2>), (<Cell u'\u8054\u7cfb\u4eba'.A3>, <Cell u'\u8054\u7cfb\u4eba'.B3>, <Cell u'\u8054\u7cfb\u4eba'.C3>, <Cell u'\u8054\u7cfb\u4eba'.D3>, <Cell u'\u8054\u7cfb\u4eba'.E3>, <Cell u'\u8054\u7cfb\u4eba'.F3>, <Cell u'\u8054\u7cfb\u4eba'.G3>, <Cell u'\u8054\u7cfb\u4eba'.H3>, <Cell u'\u8054\u7cfb\u4eba'.I3>, <Cell u'\u8054\u7cfb\u4eba'.J3>), (<Cell u'\u8054\u7cfb\u4eba'.A4>, <Cell u'\u8054\u7cfb\u4eba'.B4>, <Cell u'\u8054\u7cfb\u4eba'.C4>, <Cell u'\u8054\u7cfb\u4eba'.D4>, <Cell u'\u8054\u7cfb\u4eba'.E4>, <Cell u'\u8054\u7cfb\u4eba'.F4>, <Cell u'\u8054\u7cfb\u4eba'.G4>, <Cell u'\u8054\u7cfb\u4eba'.H4>, <Cell u'\u8054\u7cfb\u4eba'.I4>, <Cell u'\u8054\u7cfb\u4eba'.J4>), (<Cell u'\u8054\u7cfb\u4eba'.A5>, <Cell u'\u8054\u7cfb\u4eba'.B5>, <Cell u'\u8054\u7cfb\u4eba'.C5>, <Cell u'\u8054\u7cfb\u4eba'.D5>, <Cell u'\u8054\u7cfb\u4eba'.E5>, <Cell u'\u8054\u7cfb\u4eba'.F5>, <Cell u'\u8054\u7cfb\u4eba'.G5>, <Cell u'\u8054\u7cfb\u4eba'.H5>, <Cell u'\u8054\u7cfb\u4eba'.I5>, <Cell u'\u8054\u7cfb\u4eba'.J5>)]

log0711 <Cell u'\u8054\u7cfb\u4eba'.B2> lily

log0711 <type 'unicode'>

assert word: [email protected]

Process finished with exit code 0

The login.py file can also create a log after executing the login action to indicate successful login.

At this point, the main program has implemented reading data, logging in to mailboxes, adding contacts, and writing test results to excel. The basic functions have been completed. Now let’s do one more thing and it will be close to perfect, which is the encapsulation of time. Call the time function in the program to write the specified time format.

Step 13—Encapsulation of common time operations
Create a new FormatTime.py under the Util package
FormatTime.py

#encoding=utf-8

#author-Xia Xiaoxu

#encoding=utf-8

import time

from datetime import timedelta,date

def date_time_chinese():

    print u"returns the current time string,format for YYYY year mm month dd day HH hour MM minute SS second"

    return time.strftime("%Y year %m month %d day %H hour %M minute %S second", time.localtime())

def date_chinese():

    print u"returns the current time string, format for YYYY年mm月dd日"

    return time.strftime("%Y year %m month %d day",time.localtime())

def time_chinese():

    print u"returns the current time string,format for HH时 MM分 SS秒"

    return time.strftime("%H hour %M minute %S second", time.localtime())

def date_time():

    print "returns the current time string, format for YYYY-mm-dd HH:MM:SS"

    return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())

def date_time_slash():

    print "returns the current time string,format for YYYY/mm/dd HH:MM:SS"

    return time.strftime("%Y/%m/%d %H:%M:%S",time.localtime())

def dates():

    print "returns the current time string,format for YYYY-mm-dd"

    return time.strftime("%Y-%m-%d",time.localtime())

def date_slash():

    print "returns the current time string,format for YYYY/mm/dd"

    return time.strftime("%Y/%m/%d",time.localtime())

def times():

    print "returns the current time string, format for HH:MM:SS"

    return time.strftime("%H:%M:%S",time.localtime())

def year():

    print "returns the current time string,format for year"

    return time.strftime("%Y",time.localtime())

def month():

    print "returns the current time string,format for month"

    return time.strftime("%m",time.localtime())

def day():

    print "returns the current time string,format for day"

    return time.strftime("%d",time.localtime())

def hour():

    print "returns the current time string, format for Hour"

    return time.strftime("%H",time.localtime())

def minute():

    print "returns the current time string,format for minute"

    return time.strftime("%M",time.localtime())

def seconds():

    print "return the current time string,format for seconds"

    return time.strftime("%S",time.localtime())

def str_to_tuple(stime):

    print "returns the string variable into time tuples"

    return time.strptime(stime,"%Y-%m-%d %H:%M:%S")

def add_date(day_num):

    today=date.today()

    print "returns the current date-%s and a time interval-%s" %(today,day_num)

    times=today+timedelta(days=day_num)

    return times

def sub_date(day_num):

    today=date.today()

    print "returns the current date-%s minus one time interval-%s" %(today,day_num)

    times=today-timedelta(days=day_num)

    return times

if __name__=='__main__':

    #Test code

    print date_time_chinese()

    print date_chinese()

    print time_chinese()

    print date_time()

    print date_time_slash()

    print dates()

    print date_slash()

    print times()

    print year()

    print month()

    print day()

    print hour()

    print minute()

    print seconds()

    time1=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())

    print str_to_tuple(time1)

    print add_date(2)

    print sub_date(2)

Result: ok, Chinese does not need to be transcoded in pycharm, but transcoding is required to run in notepad.

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/Util/FormatTime.py

returns the current time string,format for YYYY year mm month dd day HH hour MM minute SS second

July 11, 2018 23:01:36

returns the current time string, format for YYYY mm month dd day

July 11, 2018

returns the current time string, format for HH hours MM minutes SS seconds

23:01:36

returns the current time string, format for YYYY-mm-dd HH:MM:SS

2018-07-11 23:01:36

returns the current time string,format for YYYY/mm/dd HH:MM:SS

2018/07/11 23:01:36

returns the current time string,format for YYYY-mm-dd

2018-07-11

returns the current time string,format for YYYY/mm/dd

2018/07/11

returns the current time string, format for HH:MM:SS

23:01:36

returns the current time string,format for year

2018

returns the current time string,format for month

07

returns the current time string,format for day

11

returns the current time string, format for Hour

23

returns the current time string,format for minute

01

return the current time string,format for seconds

36

returns the string variable into time tuples

time.struct_time(tm_year=2018, tm_mon=7, tm_mday=11, tm_hour=23, tm_min=1, tm_sec=36, tm_wday=2, tm_yday=192, tm_isdst=-1)

returns the current date-2018-07-11 and a time interval-2

2018-07-13

returns the current date-2018-07-11 minus one time interval-2

2018-07-09

Process finished with exit code 0

Modify the main program, call the time function, and print the time
TestScript.py:

#encoding=utf-8

#author-Xia Xiaoxu

from selenium import webdriver

import time

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.common.by import By

from selenium.common.exceptions import TimeoutException, NoSuchElementException

import traceback

from PageObject.Login_Page import *

from PageObject.AddressBook import *

from Action.add_contact import *

from Action.login import *

from ProjectVar.var import *

from Util.Excel import *

from Util.log import *

from Util.FormatTime import *

driver=webdriver.Firefox(executable_path='c:\\geckodriver')

driver.get('http://mail.126.com')

pe=parseExcel(test_data_excel_path)

pe.set_sheet_by_name(u"126 account")

print pe.get_default_sheet()

rows=pe.get_all_rows()[1:]

for id,row in enumerate(rows):

    if row[4].value =='y':

        username = row[1].value

        password = row[2].value

        print username, password

        try:

            login(driver,username,password)

            pe.set_sheet_by_name(u"Contact")

            print pe.get_default_sheet()

            rows1=pe.get_all_rows()[1:]

            print "rows1:",rows1

            test_data_pass_flag=True#Result representation, used for final writing of excel results

            for id1,row in enumerate(rows1):

                if row[7].value == 'y':

                    try:

                        #print row[1].value,row[2].value,row[3].value,row[4].value,row[5].value

                        print "log0711",row[1],row[1].value

                        print "log0711",type(row[1].value)

                        #Perform the actual operation of adding contacts

                        add_contact(driver,row[1].value,row[2].value,row[3].value,row[4].value,row[5].value)

                        pe.write_cell_content(id1 + 2, 9, date_time())

                        print "assert word:",row[6].value

                        assert row[6].value in driver.page_source

                        pe.write_cell_content(id1+2,10,"pass")#assert does not report an error, indicating that the assertion is successful

                    except Exception,e:

                        #print u"Exception message 01",e.message

                        pe.write_cell_content(id1+2,10,"fail")

                        pe.write_cell_content(id1+2,9,date_time())

                        test_data_pass_flag=False#The code reaches this point, indicating that there is an exception and the test failed.

                        info(u"Exception message 01" + e.message) # Output log

                else:#The description identifier is 'n', ignore the data

                    pe.write_cell_content(id1+2,10,u"忽略")

                    pe.write_cell_content(id1 + 2, 9,date_time())

                    continue

            if test_data_pass_flag ==True:#If the flag is True, the result is successful

                pe.set_sheet_by_name(u"126 account")

                pe.write_cell_content(id+2,6,"成功")

            else:#Indicates that the flag is False

                pe.set_sheet_by_name(u"126 account")

                pe.write_cell_content(id+2,6,"Failed")

        except Exception,e:

            pe.set_sheet_by_name(u"126 account")

            #print u"Exception message 02:",e

            pe.write_cell_content(id+2,6,"fail")

            info(u"Exception message 02:"+e.message)#Output log

        time.sleep(2)

        driver.quit()

    else:#Take this branch, indicating that the identifier is "n"

        pe.set_sheet_by_name(u"126 account")

        pe.write_cell_content(id+2,6,u"忽略")

        continue

Result: OK

C:\Python27\python.exe D:/test/dataDrivenTestPractice1/TestScript/TestScript.py

126account

xiaxiaoxu1987 gloryroad

2018-07-11 23:17:39 log.py[line:19] INFO login successfully

Contact person

rows1: [(<Cell u'\u8054\u7cfb\u4eba'.A2>, <Cell u'\u8054\u7cfb\u4eba'.B2>, <Cell u'\u8054\u7cfb\u4eba'.C2>, <Cell u'\u8054\u7cfb\u4eba'.D2>, <Cell u'\u8054\u7cfb\u4eba'.E2>, <Cell u'\u8054\u7cfb\u4eba'.F2>, <Cell u'\u8054\u7cfb\u4eba'.G2>, <Cell u'\u8054\u7cfb\u4eba'.H2>, <Cell u'\u8054\u7cfb\u4eba'.I2>, <Cell u'\u8054\u7cfb\u4eba'.J2>), (<Cell u'\u8054\u7cfb\u4eba'.A3>, <Cell u'\u8054\u7cfb\u4eba'.B3>, <Cell u'\u8054\u7cfb\u4eba'.C3>, <Cell u'\u8054\u7cfb\u4eba'.D3>, <Cell u'\u8054\u7cfb\u4eba'.E3>, <Cell u'\u8054\u7cfb\u4eba'.F3>, <Cell u'\u8054\u7cfb\u4eba'.G3>, <Cell u'\u8054\u7cfb\u4eba'.H3>, <Cell u'\u8054\u7cfb\u4eba'.I3>, <Cell u'\u8054\u7cfb\u4eba'.J3>), (<Cell u'\u8054\u7cfb\u4eba'.A4>, <Cell u'\u8054\u7cfb\u4eba'.B4>, <Cell u'\u8054\u7cfb\u4eba'.C4>, <Cell u'\u8054\u7cfb\u4eba'.D4>, <Cell u'\u8054\u7cfb\u4eba'.E4>, <Cell u'\u8054\u7cfb\u4eba'.F4>, <Cell u'\u8054\u7cfb\u4eba'.G4>, <Cell u'\u8054\u7cfb\u4eba'.H4>, <Cell u'\u8054\u7cfb\u4eba'.I4>, <Cell u'\u8054\u7cfb\u4eba'.J4>), (<Cell u'\u8054\u7cfb\u4eba'.A5>, <Cell u'\u8054\u7cfb\u4eba'.B5>, <Cell u'\u8054\u7cfb\u4eba'.C5>, <Cell u'\u8054\u7cfb\u4eba'.D5>, <Cell u'\u8054\u7cfb\u4eba'.E5>, <Cell u'\u8054\u7cfb\u4eba'.F5>, <Cell u'\u8054\u7cfb\u4eba'.G5>, <Cell u'\u8054\u7cfb\u4eba'.H5>, <Cell u'\u8054\u7cfb\u4eba'.I5>, <Cell u'\u8054\u7cfb\u4eba'.J5>)]

log0711 <Cell u'\u8054\u7cfb\u4eba'.B2> lily

log0711 <type 'unicode'>

returns the current time string, format for YYYY-mm-dd HH:MM:SS

assert word: [email protected]

returns the current time string, format for YYYY-mm-dd HH:MM:SS

returns the current time string, format for YYYY-mm-dd HH:MM:SS

returns the current time string, format for YYYY-mm-dd HH:MM:SS

Process finished with exit code 0

Excel writes the results:

Summarize:

Now we start by assembling scattered functions to implement a larger function, and then organize the larger function into a larger function. In the end, what we see in the main program is the combination of independent large functions. See It looks neat, simple, highly readable, and easy to maintain.

In this way, we transform the entire framework from a scattered list of codes to encapsulating functions into pieces. We separate data and programs, encapsulate and integrate a certain independent function. In this process, we become familiar with the steps of building a framework. After knowing the ins and outs and benefits of encapsulating it into several large blocks, when you build the test framework later, you can just follow these large blocks. It will be relatively easier to accept this idea and logic and its necessity. nature, fundamentally understand why such a test framework should be built and the principles of this test framework, and then draw inferences and extend it to other types of test frameworks.

More hands-on practice~

The following is the data-driven framework structure:

Data-driven framework structure:
Action:
    encapsulated function of operating elements, such as login and adding contacts. . .

conf:
Log configuration file
Positioning element configuration file
Database configuration file
    
PageObject:
    A page is a class, and the method of the class can obtain related elements on the page

ProjectVar:
Project path
Project-related global variables
TestData: (file or excel)
test case
test data

TestScript:
The main program that runs the test framework: the entrance, which mainly reads the test data files
                      and records the test results.

Util-Tool Class
Function:
      Read configuration file
      excel tool class
      time class
          method to find elements method
          to read positioning element configuration file
          log method
          log operation
          screenshot
          report template

If you need the source code of the framework, you can leave your email in the comment area~


Finally, I will share with you the documents and learning materials that I have accumulated and truthful. If necessary, you can just pick them up. The above content should

be the most comprehensive and complete preparation warehouse for software testing friends. In order to better organize it For each module, I also referred to many high-quality blog posts and projects on the Internet, trying not to miss any knowledge point. Many friends relied on these contents to review and got offers from major manufacturers such as BATJ. This warehouse has also helped a lot. As a learner of software testing, I hope it can also help you.

Follow my WeChat official account below to get it for free! ↓ ↓ ↓ ↓ ↓

Guess you like

Origin blog.csdn.net/weixin_56331124/article/details/132840168