【工作记录】完整搭建UI自动化(Python + Playwright + Pytest+ Allure + YAML + nb_log)

可参考:

使用Playwright+Pytest+Yaml+Allure搭建UI自动化测试用例框架_自动化测试框架playwright allure-优快云博客

1、UI自动化框架_结构目录及说明

  • Python:核心编程语言,提供基础语法和丰富的第三方库支持。
  • Playwright:浏览器自动化工具,实现跨浏览器网页操作与测试。同Selenium
  • Pytest:测试框架,管理用例、断言及执行,支持扩展插件。
  • Allure:可视化测试报告工具,生成结构化结果便于问题追溯。
  • YAML:配置文件格式,结构化存储测试数据或环境参数。
  • nb_log:Python日志库,提供灵活日志记录与多线程异步输出。

AutomatedTesting
├─ common                         公共层包
├─ logs                                日志文件                  
├─ pageElement                  存放页面元素定位文件的文件夹目录
├─ testdata                           测试用例数据
├─ testScripts                       测试用例                                          
├─ util                                   工具
├─ create_tree_with_args.py   用于生成指定目录结构树
├─ nb_log_config.py               日志模板配置脚本文件
├─ README.md                     ReadMe
└─ requirements.txt                依赖包及其精确的版本号 

README.md

AutomatedTesting
├─ common                                                   公共层包目录  
│   ├─ page_action.py                                       封装常用页面组件的操作方法脚本
│   └─ __init__.py
├─ logs                                                     存放所有自动化测试用例的运行日志文件夹目录                     
│   ├─ 20231120.log                                         一个log文件代表一天中所有的日志
│   └─ 20231121.log
├─ pageElement                                              存放页面元素定位文件的文件夹目录
│   ├─ ams_main_page_element.yml                            定位文件命名应该能直观看出是代表系统中哪一个页面
│   ├─ login_page_element.yml
│   └─ main_page_element.yml
├─ testdata                                                 存放测试用例运行中输入的数据的文件夹目录
│   └─ login_test_data.yml                                  数据文件命名要能直观看出是用于哪个模块的测试用例
├─ testScripts                                              存放测试用例脚本的包目录                                                 
│   ├─ allure-report                                        所有测试用例的运行结果报告文件夹--结果统计报告是html格式
│   ├─ allure_result                                        所有测试用例的运行结果数据文件夹--结果数据文件是json格式
│   ├─ test-results                                         存放所有测试用例运行结果的截图和录屏数据
│   ├─ conftest.py                                          主要用来定义一些fixture前后置方法
│   ├─ run.py                                               运行项目中所有测试用例并生成报告
│   ├─ test_iotdevicelist.py                                测试用例--命名规则必须以“test”开头
│   ├─ test_mainpagefunc.py
│   └─ __init__.py
├─ util                                                     定义实用工具的包目录
│   ├─ dirAndTime.py                                        获取当前时间和获取当前日期
│   ├─ handle_logging.py                                    生成运行日志
│   ├─ handle_yaml.py                                       读取yml格式文件中的数据
│   └─ __init__.py
├─ create_tree_with_args.py                                 用于生成指定目录结构树
├─ nb_log_config.py                                         日志模板配置脚本文件
├─ README.md                                                ReadMe
└─ requirements.txt                                         用于记录所有依赖包及其精确的版本号,以便新环境部署

2、安装软件库

1. 安装python

如果你的电脑已经装有python且是3.8以上版本请跳过本章

打开浏览器并访问Python官网,下载windows版安装程序:https://www.python.org

下载好安装包后,右击“以管理员身份运行”,在安装对话框中勾选“Add python.exe to PATH”,选择“Customize installation”来自定义一个python安装路径注意:安装路径中不要有中文目录,需要所有目录是纯英文的)选择好安装路径后点击[Install]

安装完成后,点击“禁用路径长度限制”,然后点击[关闭]

再单击[关闭]按钮,即可结束安装

校验是否安装成功:使用快捷键“WIN+R”打开运行窗口,输入“cmd”,单击[确定]打开命令窗口,输入命令“python --version”(有的windows系统输入“python -V”),会看到安装的python版本号输出,这个时候就说明完全安装好了。

2. 安装Pycharm(社区版)

打开浏览器访问Pycharm官网:

Download PyCharm: The Python IDE for data science and web development by JetBrains

下载完毕后,根据安装向导安装即可:

选择安装路径,注意:安装路径中不要有中文目录,需要所有目录是纯英文的

建议全部勾选

点击install

安装完成后点击Finish

这时候桌面已经有pycharm快捷方式,双击快捷方式,打勾并点击继续

点击加号”+”,创建一个新项目

选择项目路径,默认C盘,我这里自定义选择,选择完毕后,最后点击Create

选择需要运行的.py文件,单击右键-run

结果如下则表示配置成功

3. 安装Java、Allure

1)安装Java

首先需要下载java开发工具包jdk,下载地址:

https://www.oracle.com/java/technologies/downloads/archive/,这里显示各种版本的jdk,建议下载1.8及以上的版本

点进去之后拉最下面选择Windows x64名字开头的安装包下载,下载时需要登录Oracle账户(没有就注册一个)。

下载完成后右击安装包->使用管理员方式运行,安装过程中可以自定义安装目录并记住安装路径(后面需要使用其配置环境变量)。注意:安装路径中不要有中文目录,需要所有目录是纯英文的

安装完成后右击“我的电脑”点击“属性”,选择“高级系统设置”

点击环境变量按钮,打开环境变量编辑窗口,在系统变量区域新建JAVA_HOME变量:

变量名:JAVA_HOME 变量值:上面的jdk安装路径(绝对路径)

再新建CLASSPATH变量:变量名:CLASSPATH 变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar

在系统变量中找到Path变量点击[编辑]按钮,打开编辑环境变量窗口,点击[新建]按钮,在底部增加一个输入框,输入%JAVA_HOME%\bin,再次点击[新建]按钮,再增加一个输入框,输入%JAVA_HOME%\jre\bin

一路点击[确定]按钮直到关掉所有环境变量设置窗口。配置完成后,右击电脑左下角windows系统图标->“运行”,输入“cmd”,在命令窗口中输入“java”回车

再输入“java -version”回车

输入以上命令回车后出现如图所示文字即代表java安装成功。

2)安装allure

由于allure需要依赖java环境,所以在上节就说明了jdk安装,接着就要下载allure包并配置环境变量:allure包下载地址:Releases · allure-framework/allure2 · GitHub

我们下载windows版的zip压缩包即可

在本地解压下载好的allure包,解压后有4个文件夹,复制bin文件夹目录路径,并用其设置allure环境变量,添加到Path变量中:

运行“cmd”打开cmd命令窗口,输入:allure --version 出现下图所示版本号即代表安装成功

4. 安装库

1. 初步使用
pip install pyaml
pip install playwright
playwright install chromium
pip install allure-pytest
pip install pytest
pip install pytest-playwright

pip install nb_log -i https://mirrors.aliyun.com/pypi/simple  

可选的镜像地址有
豆瓣           https://pypi.douban.com/simple
阿里云          https://mirrors.aliyun.com/pypi/simple
清华大学        https://pypi.tuna.tsinghua.edu.cn/simple
中国科技大学     https://pypi.mirrors.ustc.edu.cn/simple

2. 详细使用

在本地写一个requirements.txt文本文件,放在上面已创建项目的根目录下,打开cmd命令窗口进入requirements文件所在路径,执行安装第三方库的命令:

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

-i 参数代表从指定镜像源下载

这个命令的意思是从国内镜像网站下载安装requirements.txt这个文件中所有的库。

全部下载完成后,在命令窗口输入:pip list 即可看到已经安装好的库名及版本

然后执行playwright install命令安装自动化运行所需的浏览器,Playwright介绍见官网Installation | Playwright Python

建议大家平时多研究playwright官网,官网手册全面且简单易学,使用微软的Edge浏览器访问官网可以翻译成中文。为后续手写测试用例脚本打下基础。

另一个学习网站:什么是playwright?-playwright-何三笔记

PS:安装过程中如果一直安装不成功的话,说明你安装的python版本比较高,有些第三方库难以适配到,那么请卸载该python,重新下载安装较低版本的python,推荐3.9\3.10左右的版本。

3、common公共层包

1. 浏览器启动方法封装browser_manager.py
from playwright.sync_api import sync_playwright

class BrowserManager:
    def __init__(self):
        self.playwright=None
        self.browser=None
        self.page=None

    def launchChrome(self,headless=False, channel="chrome"):
        """
        launchChrome为无头模式下启动谷歌浏览器
        :param headless:
        :param channel:
        :return:
        """
        self.playwright = sync_playwright().start()
        self.browser = self.playwright.chromium.launch(headless=headless, channel=channel)
        self.page = self.browser.new_page()
        return self.page

    def close(self):
        """
        关闭浏览器、关闭playwright
        """
        self.browser.close()
        self.playwright.stop()

# 检验是否可以使用playwright
# if __name__ == "__main__":
#     # 使用示例
#     BrowserManager = BrowserManager()
#     try:
#         page =BrowserManager.launchChrome()
#         # 访问网页并执行操作
#         page.goto("https://www.baidu.com/")
#         print("当前标题:", page.title())
#         page.wait_for_timeout(2000)  # 等待2秒查看效果
#
#     finally:
#         BrowserManager.close()

4、logs日志文件                  

1)使用nb_log记录日志,配置logger
import os
import time
import logging
from nb_log import LogManager

# 获取项目根目录(更可靠的获取方式)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
LOG_DIR = os.path.join(BASE_DIR, 'logs')  # 日志目录定义

# 确保日志目录存在
os.makedirs(LOG_DIR, exist_ok=True)

def get_logger():
    """单例模式获取 Logger 对象"""
    logger_name = __name__  # 使用模块名作为 Logger 名称
    log_filename = f"{time.strftime('%Y%m%d')}.log"  # 按日期命名日志文件

    # 创建 Logger 并配置处理器
    logger = LogManager(logger_name).get_logger_and_add_handlers(
        log_level_int=logging.DEBUG,  # 使用常量提高可读性
        is_add_stream_handler=True,   # 启用控制台输出
        log_path=LOG_DIR,             # 直接使用 LOG_DIR
        log_filename=log_filename,    # 动态生成文件名
        formatter_template=logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
    )
    return logger

# 全局唯一 Logger 实例
test_log = get_logger()

if __name__ == "__main__":
    # 测试日志输出
    test_log.debug("Debug 信息(测试)")
    test_log.info("Info 信息(测试)")
 2)使用实例
from util.handle_logging import test_log  # 引入函数

# 特定位置标记插入即可
test_log.info("成功登录系统")
test_log.error("登录识别")
test_log.debug("调试内容")
test_log.warnning("提示内容")

3)报错解决(已安装包,仍提示未安装)

set PYTHONPATH=项目根目录

5、pageElement页面元素定位文件


6、testdata测试用例数据


7、testScripts测试用例           

1. 测试用例test_001
import pytest


def test_001(page):

    page.goto("https://www.baidu.com/")
    print("当前标题:", page.title())
    page.wait_for_timeout(2000)  # 等待2秒查看效果
2. 正式用例

待补充...

                 
8、util工具包


9、create_tree_with_args.py   用于生成指定目录结构树

生成目录说明:运行此脚本,复制控制台打印内容到readme.md即可

#! -*-conding=: UTF-8 -*-
# 2023/11/22 9:52
"""
    描述:python实现tree命令
"""

from pathlib import Path
import argparse

from typing import Optional

# 黑名单 不想列出的目录
blacklist = [".git", ".idea"]

# ANSI颜色代码
BLUE = "\033[34m"
WHITE = "\033[0m"


def is_hidden(file: Path) -> bool:
    return file.name.startswith(".")


def get_entries(path: Path, show_hidden: bool = False):
    entries = list(path.iterdir())
    if not show_hidden:
        entries = [entry for entry in entries if not is_hidden(entry)]
    return sorted(entries, key=lambda entry: entry.is_file())


def print_tree(path: Path, depth: Optional[int], show_hidden: bool = False, indent: str = "", is_last: bool = True):
    entries = get_entries(path, show_hidden)
    total_entries = len(entries)
    for i, entry in enumerate(entries):
        is_dir = entry.is_dir()
        entry_name = entry.name

        if i == total_entries - 1:
            branch = "└─ "
            new_indent = indent + "    " if is_last else indent + "│   "
        else:
            branch = "├─ "
            new_indent = indent + "│   "

        if is_dir:
            print(f"{indent}{branch}{BLUE}{entry_name}{WHITE}")
            if depth is None or (depth and depth > 1):
                print_tree(entry, None if depth is None else depth - 1, show_hidden, new_indent, i == total_entries - 1)
        else:
            print(f"{indent}{branch}{entry_name}")


def main():
    parser = argparse.ArgumentParser(description="Python实现tree命令")
    parser.add_argument("-p", "--path", type=str, nargs="?", default=".", help="要遍历的目录路径")
    parser.add_argument("-d", "--depth", type=int, help="限制显示的层数")
    parser.add_argument("--hidden", action="store_true", help="显示隐藏文件")
    args = parser.parse_args()
    path = Path(args.path).resolve()
    print(path)
    print_tree(path, args.depth, args.hidden)


if __name__ == "__main__":
    # 在终端窗口输入命令:python create_tree_with_args.py -d 3
    # 这个命令表示打印当前工程目录结构,且深度是3层,层数可以自定义
    main()


10、nb_log_config.py日志模板配置脚本文件


11、README.md

 使用create_tree_with_args.py生成


12、requirements.txt依赖包及其精确的版本号 

13、执行命令run.py

# 控制台执行命令:
python -m pytest -sv

集成后执行命令待补充...

14、fixture初始化、清除- conftest.py

可参考:

python3.x中 pytest之fixture - 漂泊的小虎 - 博客园

fixture是指夹具(把用例夹在中间),它包括前置工作和后置工作,前置是用例代码的准备阶段,后置是用例执行之后的清理阶段,用例是放在前置代码和后置代码

使用fixture来创建对象,启动浏览器,运行结束后再进行清除

import pytest
from common.browser_manager import BrowserManager

@pytest.fixture(scope="function")
def page():
    """
    函数初始化打开浏览器,函数结束后清除
    初始化、清除分别在前后执行,并且只会执行1次
    :return:
    """
    browser_manager = BrowserManager()
    try:
        browser_page = browser_manager.launchChrome()
        yield browser_page
    finally:
        browser_manager.close()

15、报错解决

1.  解决 AttributeError: 'str' object has no attribute 'iter_parents' 的步骤

问题原因

  • 版本冲突pytest 8.1.0 及以上版本与某些插件(如 allure-pytest 或 pytest-xdist)的兼容性被破坏,导致访问 item.nodeid 时触发 iter_parents 方法缺失的错误31
解决方案:降级 pytest 到兼容版本
# 卸载当前版本 pip uninstall pytest

# 安装指定兼容版本 pip install pytest==8.0.2

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值