Master the simplest ui automation testing framework!!!

Build the test framework and analyze the framework directory

config: configuration file. Put all project related configurations in this folder. python supports yaml and ini

ini file introduction

Start with [section]

End with [option=value]

Remarks in; start

The section name cannot be duplicated

Introduction to yaml file

Starting with --- indicates the beginning of the file

All members in the list start at the same indentation level and start with a "-" (a horizontal bar and a space)

A dictionary consists of a simple key: the form of a value (this colon must be followed by a space)

ini read file encapsulation, yaml read file encapsulation

configutil.py

import configparser
import os
import yaml
class ReadIni():
    def read_ini(file, section, option):
        conf = configparser.ConfigParser()
        conf.read(file)
        res=conf.get(section, option)
        print(res)
        return res


class ReafYaml():
    def read_yaml(file,key):
        f=open(file,encoding='utf-8')
        file_data =f.read()
        res=yaml.load(file_data,Loader=yaml.FullLoader)
        print(res.get(key))
        return res.get(key)

if __name__ == '__main__':
    current_path = os.path.dirname(os.path.realpath(__file__))
    config_path = os.path.dirname(current_path) + os.sep + "config"
    yaml_file = os.path.join(config_path, 'test.yaml')
    ReafYaml.read_yaml(yaml_file, 'username')

Data: data file. Put the test case parameterization related files here, xlsx,csv,json

Driver: driver file

Log: log files, such as test log and error log

report: Test report

Test: test file

Case test case

test.py

import unittest
from selenium import webdriver
from test.locators import *
from utils.configutil import ReadIni,ReafYaml
from test.page import *
from utils.excelutil import *
from selenium.webdriver.common.action_chains import ActionChains
import yaml
import os
from utils.logutil import *

current_path = os.path.dirname(os.path.realpath(__file__))
config_path = os.path.dirname(current_path) + os.sep + "config"
ini_file = os.path.join(config_path, 'test.ini')
ip = ReadIni.read_ini(ini_file, 'ip_address', 'ip')
# print(ip)
url = '{}user/login?redirect=http%3A%2F%2Fmis-next.aunbox.ce%2FuserDetail'.format(ip)
excel_file = os.path.join(os.path.dirname(current_path) + os.sep + "data", 'case.xlsx')
username = ReadExcel.read_excel(excel_file,'Sheet1','A')

class LoginTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)
        self.driver.get(url)

    def test_login(self):
        Logger('C:\\Users\\Administrator\\PycharmProjects\\yunding\\log\\test.log','info').info('add project')
        for user in username:
            loginpage=LoginPage(self.driver)
            loginpage.enter_username(user)
            loginpage.enter_password()
            loginpage.click_login_button()
            self.assertEqual('Super administrator',loginpage.get_login_name())
            quitlogin=self.driver.find_element_by_xpath('//*[@id="root"]/section/section/header/div[2]/span')
            ActionChains(self.driver).move_to_element(quitlogin).perform()
            self.driver.find_element_by_class_name('ant-dropdown-menu-item').click()
            self.driver.get(url)
        # self.driver.find_element(*LoginLocators.username).send_keys("{}".format(user))
        # self.driver.find_element(*LoginLocators.password).send_keys("{}".format(pad))
        # self.driver.find_element(*LoginLocators.loginbutton).click()
        # id=self.driver.find_element(*LoginLocators.loginname)
        # self.assertEqual('Super administrator ', id.text)

    def tearDown(self):
        self.driver.quit()

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

Common - test related abstract common code

Page page class

Element positioning

locators.py

from selenium.webdriver.common.by import By

# Page element
class LoginLocators():
    username=(By.ID,'account')
    password=(By.ID,'password')
    loginbutton=(By.CLASS_NAME,'ant-btn')
    loginname=(By.CLASS_NAME,'userName___fQOhV')

Element operation

page.py

from test.locators import *

# Operation of page elements
class BasePage():
    def __init__(self,driver):
        self.driver = driver

class LoginPage(BasePage):
    '''
    Operation of user login page element,,,Disappear here
    '''
    UserName = (By.XPATH,'//*[@ id="username"]) # login
    def enter_username(self,name):
        ele = self.driver.find_element(*LoginLocators.username)
        # ele.clear()
        ele.send_keys(name)  #Enter the user name element

    def enter_password(self):
        ele = self.driver.find_element(*LoginLocators.password)
        ele.send_keys('123456') #Input password

    def click_login_button(self):
        ele = self.driver.find_element(*LoginLocators.loginbutton)
        ele.click()  #Click the login button

    def get_login_name(self):
        ele = self.driver.find_element(*LoginLocators.loginname)
        return ele.text  #Return login

utils: public method

config class

log class

logutil.py

import logging
from logging import handlers

class Logger(object):
    level_relations = {
        'debug':logging.DEBUG,
        'info':logging.INFO,
        'warning':logging.WARNING,
        'error':logging.ERROR,
        'critical':logging.CRITICAL
    }

    def __init__(self,fp='d:\\Project_Redmine_01\\log\\test.log',level='info'):
        self.level = self.level_relations.get(level)
        self.logger = logging.getLogger(fp)
        self.logger.setLevel(self.level)
        formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
        th = handlers.TimedRotatingFileHandler(fp)
        th.setFormatter(formatter)
        th.setLevel(self.level)
        self.logger.addHandler(th)

    def debug(self,msg):
        self.logger.debug(msg)

    def info(self,msg):
        self.logger.info(msg)

    def warning(self,msg):
        self.logger.warning(msg)

    def error(self,msg):
        self.logger.error(msg)

    def critical(self,msg):
        self.logger.critical(msg)

if __name__ == '__main__':
    log = Logger('abcd.log','debug')
    log.info('this is info msg')
    log.critical('this is critical msg')

Read and write excel classes

excelutil.py

import configparser
import os
import yaml
class ReadIni():
    def read_ini(file, section, option):
        conf = configparser.ConfigParser()
        conf.read(file)
        res=conf.get(section, option)
        print(res)
        return res
class ReafYaml():
    def read_yaml(file,key):
        f=open(file,encoding='utf-8')
        file_data =f.read()
        res=yaml.load(file_data,Loader=yaml.FullLoader)
        print(res.get(key))
        return res.get(key)


if __name__ == '__main__':
    current_path = os.path.dirname(os.path.realpath(__file__))
    config_path = os.path.dirname(current_path) + os.sep + "config"
    yaml_file = os.path.join(config_path, 'test.yaml')
    ReafYaml.read_yaml(yaml_file, 'username')

The class that generates the report

run.py

import os
import time
import unittest
import HTMLTestRunner
current_path = os.path.dirname(os.path.realpath(__file__))
# print(current_path)
report_path = os.path.join(current_path,'report')
# print(report_path)
case_path = os.path.join(current_path,'test')
# print(case_path)
report_name = time.strftime('%Y%m%d%H%M%S',time.localtime((time.time())))

testsuite = unittest.TestLoader().discover(case_path)
filename = "{}\\{}.html".format(report_path,report_name)
f = open(filename,'wb')
runner = HTMLTestRunner.HTMLTestRunner(stream=f,title='report',description='this is a report')
runner.run(testsuite)
f.close()

Finally, I would like to thank everyone who carefully reads my article. Watching the rise and attention of fans all the way, reciprocity is always necessary. Although it is not very valuable, you can take it directly if you can use it:

These materials should be the most comprehensive and complete preparation warehouse for [software testing] friends. This warehouse also accompanies tens of thousands of test engineers through the most difficult journey. I hope it can also help you!

In my QQ technology exchange group (technology exchange and resource sharing, advertising do not disturb)

You can take it away yourself, group number: free information in 175317069 groups is the essence of the author's more than 10 year test career. And the great gods of the same industry exchange technology together

If it helps you a little, your "praise" is the biggest driving force for Xiaobian's creation. See you in the next article!

 

 

Keywords: Programmer software testing UI

Added by mikeeeeeeey on Sat, 01 Jan 2022 01:08:20 +0200