pytest+selenium+allure Marco simple de automatización de Webui

introducir

Marco de automatización fácil.

Arquitectura de software

pytest5.4.2
selenio
3.141.0
encanto_python_commons2.8.29
PyYAML
5.4.1
pitón == 3.6.0

Instalación de dependencia

使用 pip install -r requisitos.txt

Estructura de directorios

inserte la descripción de la imagen aquí
casodirectorio de archivos de caso
data_case

controladores de parámetros de casowebdriver almacena
lib
Definir registro, leer yml,
registros de decorador de tiempoalmacenar
la página del archivo de registro

Informe de encapsulación de métodos funcionalesInforme de almacenamiento
test_run

Defina la clase de inicio e inicie el comando config.ini utilizadoArchivo de configuración
connftest.py
El uso compartido global utiliza
el archivo run.py==entry

demostración en el expediente

import allure
import pytest
from page.webpage import BasePage
from lib.init_data import get_data

base_data=get_data("demo.yml")

@pytest.mark.usefixtures()
class Test_case():

    @pytest.mark.parametrize("uer",base_data['test_id'])
    @allure.feature('打开百度登录')
    def test_1(self,uer):
        d =BasePage()
        d.by_id(uer)
        assert 1==2```

formato de archivo yml

test_id:
  - "s-top-loginbtn我的","id",'我的'

paquete de controladores web

from selenium import webdriver

#封装Chrome启动的driver
def webdrivers():
    d = webdriver.Chrome()
    return d

webdrivers()

decorador de funciones

import time

#等待时间装饰器
def think_time(func):
    def thinktime(*args,**kwargs):
        time.sleep(1)
        return func(*args,**kwargs)
    return thinktime

método init_data para leer diferentes archivos de parámetros

from lib.read_data import data
import os

#对读取测试数据及ini文件的配置
BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

def get_data(file_name):

    data_file_path = os.path.join(BASE_PATH, "data_case", file_name)
    if '.yml' in file_name:
        test_data = data.load_yaml(data_file_path)
    if '.json' in file_name:
        test_data = data.load_json(data_file_path)
    if '.ini' in file_name:
        test_data = data.load_ini(data_file_path)

    return test_data

Encapsulación y configuración de registros de registradores

import os, time
import os.path
import socket
import logging
import logging.handlers

#log日志的配置封装
def singleton(cls, *args, **kw):
    instances = {
    
    }

    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return _singleton


# @singleton
class JFMlogging(object):
    def __init__(self):
        # host_name = socket.gethostname()
        # ip = socket.gethostbyname(host_name)
        log_path = 'logs'  # 日志存放目录
        if not os.path.exists(log_path):
            os.mkdir(log_path)
        log_file = os.path.join(log_path, "{}.log".format(time.strftime("%Y%m%d")))

        self.logger = logging.getLogger()
        self.logger.setLevel(logging.INFO)

        self.logging_msg_format = '[%(asctime)s] [%(levelname)s] [%(module)s.py-line:%(lineno)d] %(message)s'
        self.formater = logging.Formatter(self.logging_msg_format)

        self.fileHandler = logging.FileHandler(log_file, mode='a', encoding="UTF-8")
        self.fileHandler.setFormatter(self.formater)
        self.fileHandler.setLevel(logging.INFO)

        self.console = logging.StreamHandler()
        self.console.setLevel(logging.INFO)
        self.console.setFormatter(self.formater)

        self.logger.addHandler(self.fileHandler)
        self.logger.addHandler(self.console)

    # def getloger(self):
    #     return self.logger


log = JFMlogging().logger

read_data reescribe configparser para resolver la transcodificación

import yaml
import json
from configparser import ConfigParser
from lib.loggers import log


class MyConfigParser(ConfigParser):
    # 重写 configparser 中的 optionxform 函数,解决 .ini 文件中的 键option 自动转为小写的问题
    def __init__(self, defaults=None):
        ConfigParser.__init__(self, defaults=defaults)

    def optionxform(self, optionstr):
        return optionstr

class ReadFileData():

    def load_yaml(self, file_path):
        log.info("加载 {} 文件......".format(file_path))
        with open(file_path, encoding='utf-8') as f:
            data = yaml.safe_load(f)
        log.info("读到数据 ==>>  {} ".format(data))
        return data

    def load_json(self, file_path):
        log.info("加载 {} 文件......".format(file_path))
        with open(file_path, encoding='utf-8') as f:
            data = json.load(f)
        log.info("读到数据 ==>>  {} ".format(data))
        return data

    def load_ini(self, file_path):
        log.info("加载 {} 文件......".format(file_path))
        config = MyConfigParser()
        config.read(file_path, encoding="UTF-8")
        data = dict(config._sections)
        return data

data = ReadFileData()

operación inicial de la página web y métodos públicos

from lib.init_data import get_data
from lib.func import think_time
import os
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

BASE_CONF = get_data(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "config.ini"))['App']


class WebPage():
    #读取config.ini中的配置
    def __init__(self,d):
        self.d = d
        self.web = BASE_CONF['URL_NAME']
        self.time_out = BASE_CONF['WAIT_TIMEOUT']


class BasePage(WebPage):
    #初始化
    def __init__(self):
        self.driver = webdriver.Chrome()
        self.wait = WebDriverWait(self.driver,10)
        self.driver.maximize_window()
        WebPage.__init__(self,self.driver)
        self.openBaidu()

    def openBaidu(self):
        #默认打开百度
        self.d.get(self.web)
#————————————————————————————————————封装公共方法——————————————————————————————————————————

    def by_id(self,id):
        self.d.find_element_by_id(id).click()

    def by_class(self,classname):
        self.d.find_element_by_class_name(classname).click()

run_test define elementos y comandos de inicio

import pytest
import os

#定义启动项
class RunTest():
    def _runpytest(self):
        pass
#pytest启动
    @staticmethod
    def run_alltest():
        # # 执行pytest单元测试,生成 Allure 报告需要的数据存在 /temp 目录,使用--clean-alluredir 覆盖之前的json文件
        # pytest.main(['-s', '-q','--alluredir', './report','--clean-alluredir'])
        # # 执行命令 allure generate ./temp -o ./report --clean ,生成测试报告
        # # os.system(" allure generate ./report/result_allure -o ./report/result_html -c")

        pytest.main(['-s', '-q', '--alluredir', './report', '--clean-alluredir'])
        os.system('allure generate ./report -o ./report/temp --clean')

Connftest define el controlador global

import pytest
import drivers.webdriver
from lib.loggers import log

#初始化全局 driver
@pytest.fixture(scope='class',autouse=True)
def driver():
    try:
        global driver
        driver =drivers.webdriver.webdrivers()
        return driver
    except Exception as e:
        log.info('初始化webdriver{}'.format(e))

ejecutar archivo de entrada

from test_run import run_test


#入口文件
class startest(run_test.RunTest):
    import time
    test_data = time

if __name__ == '__main__':
    startest.run_alltest()

También es una etapa de aprendizaje para usarlo en el trabajo. El maestro le dará consejos después de leerlo. Si no le gusta, no lo rocíe. ¡Es solo un pequeño registro personal! ! !
Código fuente: https://gitee.com/zc119/web-ui.git

Supongo que te gusta

Origin blog.csdn.net/qq_34004131/article/details/117810765
Recomendado
Clasificación