Python+Selenium+uniitest项目实战(一)

本项目是基于Python语言的前台自动化,使用的是Unittest框架(后续会优化Pytest框架)。PO模式,将测试对象(页面元素)与测试用例(元素操作+测试数据)进行分离。

项目包含以下几个部分:

Common:公共部分-对seleniumAPI的二次封装、日志输出、报错截图、读取yaml配置文件  configer :项目的配置信息  OutPuts:输出-日志、报告、截图  PageLocators:页面元素定位  PageObject:页面操作  TestCases:测试用例  TestData:测试数据  runner.py 主程序入口

 

Common:公共部分-对seleniumAPI的二次封装、日志输出、报错截图、读取yaml配置文件

 

configer :项目的配置信息

OutPuts:输出-日志、报告、截图

PageLocators:页面元素定位

PageObject:页面操作

TestCases:测试用例

TestData:测试数据

runner.py 主程序入口

 

BasePage.py

'''对selenium的基本api进行二次封装。添加日志/截图/异常处理功能。'''
from datetime import datetime

from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from Common.loghandler import logger
from web_test.configer.setting import Config


class BasePage:
    # 通过driver: WebDriver指定为driver类型,这样有自动补全提示
    def __init__(self, driver: WebDriver):
        self.driver = driver

    # 等待元素可见
    def wait_ele_visible(self, page_name, loc, timeout=30, poll_fre=1):
        logger.info(f'等待{loc}元素可见')
        try:
            WebDriverWait(self.driver, timeout, poll_frequency=poll_fre).until(EC.visibility_of_element_located(loc))
        except:
            self.save_page_shot(page_name)
            logger.error(f'等待{loc}元素可见失败,保存截图')
            raise

    # 查找元素
    def find_ele(self, page_name, loc):
        logger.info(f'查找元素{loc}')
        try:
            ele = self.driver.find_element(*loc)
        except:
            self.save_page_shot(page_name)
            logger.error(f'查找元素{loc}失败')
            raise
        else:
            return ele

    # 查找元素组
    def find_eles(self, page_name, loc):
        logger.info(f'查找所有元素{loc}')
        try:
            eles = self.driver.find_elements(*loc)
        except:
            self.save_page_shot(page_name)
            logger.error(f'查找元素{loc}失败')
            raise
        else:
            return eles

    # 点击元素
    def click_ele(self, page_name, loc, timeout=10, poll_fre=1):
        logger.info(f'在{page_name}页面执行点击元素{loc}操作')
        self.wait_ele_visible(page_name, loc, timeout, poll_fre)
        ele = self.find_ele(page_name, loc)
        try:
            ele.click()
        except:
            self.save_page_shot(page_name)
            raise

    # 输入
    def input_text(self, page_name, loc, value, timeout=10, poll_fre=1):
        logger.info(f'在{page_name}页面向元素{loc}执行输入操作')
        self.wait_ele_visible(page_name, loc, timeout, poll_fre)
        ele = self.find_ele(page_name, loc)
        try:
            ele.send_keys(value)
        except:
            logger.error('元素输入失败')
            self.save_page_shot(page_name)
            raise

    # 获取元素属性
    def get_ele_attribute(self, page_name, loc, attr_name, timeout=10, poll_fre=1):
        logger.info(f'在{page_name}页面获取{loc}元素的属性{attr_name}')
        # self.wait_ele_visible(page_name, loc, timeout, poll_fre)--获取元素属性不一定要元素可见
        ele = self.find_ele(page_name, loc)
        try:
            attribute = ele.get_attribute(attr_name)
        except:
            logger.error('获取元素属性失败')
            self.save_page_shot(page_name)
            raise
        else:
            logger.info(f'在{page_name}页面获取到{loc}元素的属性{attr_name}:{attribute}')
            return attribute

    # 获取文本
    def get_ele_text(self, page_name, loc, timeout=10, poll_fre=1):
        logger.info(f'在{page_name}页面获取{loc}元素的文本')
        self.wait_ele_visible(page_name, loc, timeout, poll_fre)
        try:
            ele_text = self.find_ele(page_name, loc)
        except:
            logger.info('获取文本失败')
            self.save_page_shot(page_name)
            raise
        else:
            logger.info(f'在{page_name}页面获取到{loc}元素文本:{ele_text}')
            return ele_text

    # 保存失败页面截图
    def save_page_shot(self, page_name):
        # 截图名称:路径 + 时间戳 + 图片描述
        # 从配置文件中获取截图文件放置路径
        filedir = Config.screenshot_path
        curr_time = datetime.now().strftime('%Y%m%d-%H%M%S')
        file_name = filedir + curr_time + page_name + '.png'
        self.driver.save_screenshot(file_name)
        logger.error(f'元素操作失败,截图{file_name}已保存')

loghandler.py

# encoding=utf8
'''封装日志处理'''
import datetime
import logging
import os
from Common.yamlconfhandler import yaml_data
from web_test.configer.setting import Config


class LoggerHandle(logging.Logger):
    def __init__(self,
                 filename=None,
                 name='root',
                 level='WARNING',
                 format ='[%(asctime)s-%(name)s]-[%(filename)s-%(funcName)s-%(lineno)s]-[%(levelname)s]--%(message)s',
                 ):
        super().__init__(name)
        self.setLevel(level)
        if filename:
            file_handler = logging.FileHandler(filename, mode='a', encoding='utf-8')
            file_handler.setLevel(level)
            fmt = logging.Formatter(format)
            file_handler.setFormatter(fmt)
            self.addHandler(file_handler)
        else:
            stream_handler = logging.StreamHandler()
            stream_handler.setLevel(level)
            fmt = logging.Formatter(format)
            stream_handler.setFormatter(fmt)
            self.addHandler(stream_handler)


log_dir = Config.log_dir
curr_date = datetime.datetime.now().strftime('%Y-%m-%d')
logName = os.path.join(log_dir, curr_date + '.Logs')
logger = LoggerHandle(filename=logName, name=yaml_data['logger']['name'], level=yaml_data['logger']['level'])


if __name__ == '__main__':
    logger.warning('warning info-------------------------')

yamlconfhandler.py

# encoding=utf8
'''yaml读取配置文件方法'''
import yaml
from web_test.configer.setting import Config


class YamlHandler:
    def __init__(self, file, encoding='utf8'):
        self.file = file
        self.encoding = encoding

    def yaml_read(self, key=None):
        with open(self.file, encoding=self.encoding)as f:
            data = yaml.load(f.read(), yaml.FullLoader)
            try:
                if key == None :
                    return data
                else:
                    return data[key]
            except:
                return '读取异常……'

    def yaml_write(self, message):
        with open(self.file, mode='w', encoding=self.encoding)as f:
            yaml.dump(message, stream=f, allow_unicode=True)


yaml_data = YamlHandler(Config.yaml_conf_path).yaml_read()


if __name__ == '__main__':
    print(yaml_data)

用来保存项目的配置信息

 

 

 用来保存项目的配置信息

conf.yaml

logger:
  level: DEBUG
  name: root
  days: 7
database:
  database: xxxxx
  host:xxxxx
  password: 123456
  port: 3306
  user: xxxxx

setting.py

# encoding=utf8
import os


class Config:

    # 获取到项目目录
    root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    cur_path = os.path.dirname(os.path.abspath(__file__))
    # yaml 配置文件路径
    yaml_conf_path = os.path.join(cur_path, 'conf.yaml')
    # 获取到测试数据所在目录
    data_path = os.path.join(root_path, r'data\test_data.xlsx')
    # 测试用例所在目录
    testcase_path = os.path.join(root_path, 'testcases')
    # log日志所在目录
    log_dir = os.path.join(root_path, r'Outputs\Logs')
    if not os.path.exists(log_dir):
        os.mkdir(log_dir)
    # report 测试报告所在目录
    report_dir = os.path.join(root_path, r'Outputs\AllureReport')
    if not os.path.exists(report_dir):
        os.mkdir(report_dir)
    # 屏幕截图保存路径
    screenshot_path = os.path.join(root_path, r'Outputs\ScreenShots\\')
    enviroment_file_path = os.path.join(cur_path, 'environment.properties')
    categories_file_path = os.path.join(cur_path, 'categories.json')

    base_url = 'http://xxxxxxxxx'
    login_url = base_url + '/Index/login.html'


if __name__ == '__main__':
    print(Config.root_path)
    print(Config.screenshot_path)

 

posted @ 2021-01-26 15:19  小幸运||  阅读(381)  评论(0)    收藏  举报