pytest+selenium+allure Webui automation simple framework

introduce

Easy automation framework.

Software Architecture

pytest5.4.2
selenium
3.141.0
allure_python_commons2.8.29
PyYAML
5.4.1
python==3.6.0

Dependency installation

使用 pip install -r requirements.txt

Directory Structure

insert image description here
casecase file directory
data_case
case parameter
driverswebdriver stores
lib
Define log, read yml, time decorator
logsstore log file
page
Functional method encapsulation
reportReport storage
test_run

Define the startup class and start the command config.ini usedConfiguration file
connftest.py
Global sharing uses
run.py==entry file

demo in the case file

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```

yml file format

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

webdriver package

from selenium import webdriver

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

webdrivers()

func decorator

import time

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

init_data method to read different parameter files

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

Loggers log encapsulation and configuration

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 rewrites configparser to solve transcoding

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()

webpage initial operation and public methods

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 defines startup items and commands

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 defines the global driver

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))

run entry file

from test_run import run_test


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

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

It is also a learning stage to use it at work. The master will give pointers after reading it. If you don’t like it, don’t spray it. It’s just a small personal record! ! !
Source code: https://gitee.com/zc119/web-ui.git

Guess you like

Origin blog.csdn.net/qq_34004131/article/details/117810765