python+selenium+unittest automated testing framework

Keywords: unit testing software testing

preface

About the introduction of automated testing, there are many materials on the Internet, which will not be repeated here. UI automated testing is a kind of automated testing and the top layer of the test pyramid. selenium is an automated testing tool applied to the web. It supports multi platform, multi browser and multi language to realize automation. Its advantages are as follows:

① Open source, free and good support for web interface;;

② Multi browser support: chrome, Firefox, IE, Edge, etc;

③ Multi platform support: Linux, Windows, MAC;

④ Multilingual support: java, python, Ruby, c#, JavaScript, C + +;

⑤ Simple (API simple), flexible (development language driven), supporting distributed test case execution;

Environmental preparation

  • Browser (Chrome)
  • Python
  • Selenium
  • chromedriver (please download the driver of the corresponding version of Chrome)
  • IDE(Pycharm)

1. python and pycharm installation

2. selenium installation

pip install selenium ​

selenium element positioning is the basis and key to web automation testing. There are eight positioning methods, including id, class, xpath and so on

3. chromedriver driver installation

Driver download: http://chromedriver.storage.googleapis.com/index.html

Then copy chromedriver.exe to the chrome installation directory... \ Google\Chrome\Application \, and add the chrome installation directory to the path environment variable.

4. Rapid verification test

Automated test framework

  • The config directory stores files related to the test configuration. The file type is ini, including the test website, browser driver and other information
  • The basic class base of the page is stored in the framework directory_ Page: encapsulates some common page operation methods; Log class Logger: encapsulates log output and console output methods
  • logs is used to store the output log files
  • pageobjects directory stores page objects. A page is encapsulated as a class and an element is encapsulated as a method
  • The screenshots directory stores the relevant screenshots during the test
  • test_report is used to store the output test report
  • The testsuites directory stores test cases, including test_base and individual test cases

1. config.ini configuration information is as follows:

2. Base under framework directory_ Encapsulation of page:

import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select
import os.path
from framework.logger import Logger
 
# Create a log instance
logger = Logger(logger="BasePage").getlog()
 
class BasePage(object):
    """
    Define a page base class, let all pages inherit this class, and encapsulate some common page operation methods
    """
    def __init__(self, driver):
        self.driver = driver
 
        #get an url link
    def open(self,url):
        self.driver.get(url)
 
        #quit browser and end testing
    def quit_browser(self):
        self.driver.quit()
 
        # Browser forward operation
    def forward(self):
        self.driver.forward()
        logger.info("Click forward on current page.")
 
        # Browser back operation
    def back(self):
        self.driver.back()
        logger.info("Click back on current page.")
 
        # Display wait
    def wait(self,loc,seconds):
        try:
            wait_=WebDriverWait(self.driver,seconds)
            wait_.until(lambda driver:driver.find_element(*loc))
            logger.info("wait for %d seconds." % seconds)
        except NameError as e:
            logger.error("Failed to load the element with %s" % e)
 
        # Save picture
    def get_windows_img(self):
        """
        hold file_path Save to a folder in the root directory of our project.\Screenshots lower
        """
        file_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/screenshots/'
        rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
        screen_name = file_path + rq + '.png'
        try:
            self.driver.get_screenshot_as_file(screen_name)
            logger.info("Had take screenshot and save to folder : /screenshots")
        except NameError as e:
            logger.error("Failed to take screenshot! %s" % e)
            self.get_windows_img()
 
         # Positioning element method
    def find_element(self,loc):
        """
        :return: element
        """
        return self.driver.find_element(*loc)
 
        # input
    def send_keys(self, selector, text):
 
        el = self.find_element(selector)
        el.clear()
        try:
            el.send_keys(text)
            logger.info("Had type \' %s \' in inputBox" % text)
        except NameError as e:
            logger.error("Failed to select in input box with %s" % e)
            self.get_windows_img()
 
        # Clear text box
    def clear(self, selector):
 
        el = self.find_element(selector)
        try:
            el.clear()
            logger.info("Clear text in input box before typing.")
        except NameError as e:
            logger.error("Failed to clear in input box with %s" % e)
            self.get_windows_img()
 
        # Click element
    def click(self, selector):
 
        el = self.find_element(selector)
        try:
            el.click()
            logger.info("The element \'%s\' was clicked." % el.text)
        except NameError as e:
            logger.error("Failed to click the element with %s" % e)
 
 
        #Mouse event (left click)
    def move_element(self,loc,sloc):
        mouse=self.find_element(loc)
        try:
            ActionChains(self.driver).move_to_element(mouse).perform()
            self.click(sloc)
            pass
        except Exception as e:
            logger.error("Failed to click move_element with %s" % e)
            self.get_windows_img()
 
        # Forced waiting
    @staticmethod
    def sleep(seconds):
        time.sleep(seconds)
        logger.info("Sleep for %d seconds" % seconds)

logger log input method:

import logging
import os.path
import time
 
class Logger(object):
    def __init__(self, logger):
        '''''
            Specify the file path to save the log, the log level, and the call file
            Save the log to the specified file
        '''
        # Create a logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)
 
        # Create a handler to write to the log file
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        log_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/logs/'
        log_name = log_path + rq + '.log'
        fh = logging.FileHandler(log_name)
        fh.setLevel(logging.INFO)
 
        # Create another handler for output to the console
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)
 
        # Define the output format of the handler
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
 
        # Add handler to logger
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)
 
    def getlog(self):
        return self.logger

3. For reference on how to write page objects:

Page object inherits from base_page base class

from framework.base_page import BasePage
from selenium.webdriver.common.by import By
from framework.logger import Logger
 
logger = Logger(logger="cloud_page").getlog()
class Cloud(BasePage):
    #positioner
    input_box = (By.ID,'kw')
    search_submit = (By.XPATH,'//*[@id="su"]')
 
    def value_input(self, text):
        self.wait(self.input_box,5)
        self.send_keys(self.input_box, text)
 
    def submit_btn(self):
        self.click(self.search_submit)
        logger.info("show results!")
        self.sleep(2)

4. In the test suite part, the pre use case preparation setup and cleaning teardown to be executed for each use case are written in test_ In the base file, a single test case file inherits from it

from selenium import webdriver
import unittest
 
class TestBase(unittest.TestCase):
    def setUp(self):
        self.driver=webdriver.Chrome()   #Drive browser
        self.driver.implicitly_wait(10)  #Set implicit wait
        self.driver.maximize_window()    #Maximize browser
 
    def tearDown(self):
        self.driver.quit()
 
if __name__=='__main__':
    unittest.main()

Test case reference. Note that the test case method name must start with test

import time
from testsuites.test_base import TestBase
from pageobjects.baidu_page import Cloud
 
class BaiduSearch(TestBase):
 
    def test_baidu_search(self):
        """
        There must be test At the beginning, the test logic code is encapsulated in a test In the first method.
        :return:
        """
        input = Cloud(self.driver)
        input.open('https://www.baidu.com/')
        input.value_input('selenium')  # Calling methods in page objects
        input.submit_btn()  # Call the click search button method in the page object class
        time.sleep(2)
        input.get_windows_img()  # Call the base class screenshot method
        try:
            assert 'selenium' in 'selenium'
            print('Test Pass.')
        except Exception as e:
            print('Test Fail.', format(e))

5. Finally, the core code, testrunner.py, is used to execute test cases in batches and generate test reports by referencing the HTMLTestRunner module.

import unittest
from HTMLTestRunner import HTMLTestRunner
import time
import os
 
# Define the file location and name of the output
DIR = os.path.dirname(os.path.abspath(__file__))
now = time.strftime("%Y%m%d%H%M", time.localtime(time.time()))
 
filename =now+"report.html"
#The discover method executes the test suite
testsuite = unittest.defaultTestLoader.discover(
   start_dir='./testsuites',
   pattern='*case.py',
   top_level_dir=None
   )
 
with open(DIR+'/test_report/'+filename,'wb') as f:
    runner = HTMLTestRunner(
       stream=f,
       verbosity=2, 
       title='gateway UI report',
       description='Implementation',
       tester='tester'
   )
    runner.run(testsuite)

6. Test report display

summary

The web automation framework based on selenium is not only lightweight but also flexible, and can quickly develop automated test cases. The framework design in this article is relatively simple. I hope it will help you in the design and implementation of web automation framework in the future, communicate and make progress together!

After reading some praise and forming good habits, today is better than yesterday!

The following is the supporting information. For the friends doing [software testing], it should be the most comprehensive and complete war preparation warehouse. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you!

Finally, it can be in the official account: programmer Hao.  ! Get a 216 page interview document of Software Test Engineer for free. And the corresponding video learning tutorials for free!, It includes basic knowledge, Linux essentials, Shell, Internet program principles, Mysql database, special topics of packet capture tools, interface test tools, test advanced Python programming, Web automation test, APP automation test, interface automation test, advanced continuous test integration, test architecture, development test framework, performance test, security test, etc.

If my blog is helpful to you and you like my blog content, please click "like", "comment" and "collect" for three times! Friends who like software testing can join our testing technology exchange group: 310357728 (there are various software testing resources and technical discussions)

Posted by spicey on Mon, 22 Nov 2021 19:12:36 -0800