Unittest of software testing realizes multi-account switching and login and uses Page Object design pattern to separate code

Keywords: Selenium Python Attribute

Implementing 3000 + Concurrent Pressure Measurement of Cloud Server with Jmeter

A simple understanding of Unittest and Page Object design patterns:

Unitest is a unit testing framework that comes with Python. It can be used as a case organization execution framework for automated testing frameworks.

  • Advantages: Provide us with use case organization and execution methods, comparative methods, rich logs and clear reports, etc.

The general flow of Unitest operation:

  1. TestCase is the test case that we often call it.
  2. Then the TestCase is loaded by TestLoader to TestSuite (that is, a collection of test cases)
  3. Finally, TextTest Runner runs TestSuite and saves the results to TextTest Result
  4. When executed from the command line or unittest.main(), the main() calls the run() method in TextTestRunner to execute, or the test case can be executed directly through TextTestRunner. When Runner executes, the result of execution will be output to the console by default. In order to view the output easily, we can use logging log to manage the output, and can output the result directly to the specified file.

Page Object is one of the best design patterns in Selenium's automated test development practice. It reduces code redundancy by encapsulating interface elements. At the same time, in the later maintenance, once the location of elements changes, we only need to adjust the encapsulated code of page elements, which can improve the dimensionality of test cases. Protective sex.

The Page Object design pattern is used to reconstruct the written code for the login test case of pea pod written earlier. The idea of reconstructing is as follows:

  1. Extract common content (such as canceling updates, skipping element locations, etc.)
  2. Separation of element location methods and element attribute values from business code
  3. Independently encapsulate the login function into a module
  4. Finally, unittest is used for overall planning.

Code implementation:

1. Separate encapsulation of startup information for Pea Pod App

xgCaps.py

from appium import webdriver
import yaml, logging, logging.config

log_file = '../log.conf'
logging.config.fileConfig(log_file)
logging = logging.getLogger()

def appium_caps():
    file = open('../appium_two/wdj_capability.yaml', 'r')
    data = yaml.load(file, Loader=yaml.FullLoader)

    xg_caps = {}
    xg_caps['platformName'] = data['platformName']
    xg_caps['platformVersion'] = data['platformVersion']
    xg_caps['deviceName'] = data['deviceName']

    xg_caps['appPackage'] = data['appPackage']
    xg_caps['appActivity'] = data['appActivity']

    xg_caps['noReset'] = data['noReset']
    xg_caps['unicodeKeyboard'] = data['unicodeKeyboard']
    xg_caps['resetKeyboard'] = data['resetKeyboard']

    logging.info('start app ......')
    driver = webdriver.Remote('http://'+str(data['ip'])+':'+str(data['port'])+'/wd/hub', xg_caps)

    driver.implicitly_wait(6)
    return driver

if __name__ == '__main__':
    appium_caps()

2. Encapsulating a baseView.py Class

In this base class, we mainly encapsulate the initialization of driver and the positioning of elements.

class BaseView(object):
    def __init__(self, driver):
        self.driver = driver

    def find_element(self, *location):
        return self.driver.find_element(*location)

3. Encapsulating a common class general_class.py

In this public class, we mainly prepare for the later implementation of multi-account switching login, because there may be updates and skipped images when multi-account login.

from page_unit.baseView import BaseView
from selenium.common.exceptions import NoSuchElementException
from page_unit.xgCaps import appium_caps
from selenium.webdriver.common.by import By
import logging

class general_view(BaseView):
    cancelBtn = (By.ID, 'com.wandoujia.phoenix2:id/s5')
    jumpBtn = (By.ID, 'com.wandoujia.phoenix2:id/v8')

    def click_cancelBtn(self):
        logging.info('*' * 10 + 'cancelBtn' + '*' * 10)
        try:
            cancel_element = self.driver.find_element(*self.cancelBtn)
        except NoSuchElementException:
            logging.info('cancelBtn is not found !')
        else:
            logging.info('click cancelBtn')
            cancel_element.click()

    def click_jumpBtn(self):
        logging.info('-' * 10 + 'jumpBtn' + '-' * 10)
        try:
            jump_element = self.driver.find_element(*self.jumpBtn)
        except NoSuchElementException:
            logging.info('jumpBtn is not fond !')
        else:
            logging.info('click jumpBtn')
            jump_element.click()

if __name__ == '__main__':
    driver = appium_caps()
    general = general_view(driver)
    general.click_cancelBtn()
    general.click_jumpBtn()

4. Encapsulating login operations

In this step of operation, you will use a By module, which is relatively simple and easy to understand, oh, just need to specify which positioning method to use, and then follow the positioning method of this element corresponding to the content.

by.py Content

class By(object):
    """
    Set of supported locator strategies.
    """

    ID = "id"
    XPATH = "xpath"
    LINK_TEXT = "link text"
    PARTIAL_LINK_TEXT = "partial link text"
    NAME = "name"
    TAG_NAME = "tag name"
    CLASS_NAME = "class name"
    CSS_SELECTOR = "css selector"

As for the specific use of the class By, you can see the following login_view.py

from page_unit.general_class import general_view
from page_unit.xgCaps import appium_caps
from selenium.webdriver.common.by import By
import logging

class login_view(general_view):
    # Main Navigation Menu
    navigation_element = (By.ID, 'com.wandoujia.phoenix2:id/w4')
    # Setting menu
    setting_element = (By.ID, 'com.wandoujia.phoenix2:id/pp_item_setting')
    # Sign in
    login_element = (By.ID, 'com.wandoujia.phoenix2:id/ow')
    # User name, password
    username_element = (By.ID, 'com.wandoujia.phoenix2:id/l_')
    password_element = (By.ID, 'com.wandoujia.phoenix2:id/la')
    # check box
    checkBox_element = (By.ID, 'com.wandoujia.phoenix2:id/mw')
    # Logon button
    loginBtn_element = (By.ID, 'com.wandoujia.phoenix2:id/mf')

    def login_action(self, username, password):
        self.click_jumpBtn()
        self.click_cancelBtn()
        logging.info('=' * 10 + 'login_action' + '=' * 10)
        self.driver.find_element(*self.navigation_element).click()
        self.driver.find_element(*self.setting_element).click()
        self.driver.find_element(*self.login_element).click()
        logging.info('username is: %s' % username)
        self.driver.find_element(*self.username_element).send_keys(username)
        logging.info('password is: *************')
        self.driver.find_element(*self.password_element).send_keys(password)
        logging.info('check the box')
        self.driver.find_element(*self.checkBox_element).click()
        logging.info('click loginBtn')
        self.driver.find_element(*self.loginBtn_element).click()

if __name__ == '__main__':
    driver = appium_caps()
    login = login_view(driver)
    login.login_action('User name', 'Password')

5. Using unittest Use Case Encapsulation

5.1 Encapsulation of configuration at start and end of use cases

xgunit.py

from page_unit.xgCaps import appium_caps
import unittest, logging
from time import sleep

class startAndEnd(unittest.TestCase):

    def setUp(self):
        logging.info('-' * 10 + 'setUp' + '-' * 10)
        self.driver = appium_caps()

    def tearDown(self):
        logging.info('=' * 10 + 'tearDown' + '=' * 10)
        sleep(5)
        self.driver.close_app()

5.2 Encapsulation of logins for multiple accounts

xg_login.py

from page_unit.login_view import login_view
from page_unit.xgUnit import startAndEnd
import logging, unittest

class TestLogin(startAndEnd):

    def test_login_first(self):
        logging.info('-' * 10 + 'first' + '-' * 10)
        first = login_view(self.driver)
        first.login_action('User name', 'Password')

    def test_login_second(self):
        logging.info('=' * 10 + 'second' + '=' * 10)
        second = login_view(self.driver)
        second.login_action('User name', 'Password')

    def test_login_third(self):
        logging.info('*' * 10 + 'third' + '*' * 10)
        third = login_view(self.driver)
        third.login_action('User name', 'Password')

if __name__ == '__main__':
    unittest.main()

6. Implementation process and results

Log and console printing of execution:

 

 

Posted by compguru910 on Tue, 03 Sep 2019 23:54:37 -0700