Loading

二、playwright+pytest-进阶篇-demo实战

本文demo是学习虫师的博客。附上虫师的链接:https://www.cnblogs.com/fnng/p/14311181.html
本文demo用到的源码在:https://github.com/zhangxiaoxueya/playwright-pytest-demo

一、目录结构

  • common:公用文件
    • config-配置相关
    • log-日志文件
    • util-公用方法
  • data:数据源
    • 可以放各种类型(json、yaml、图片等)
  • log:日志文件夹
  • page:页面元素
    • 按照不同的页面/模块。进行分类,将元素提取到该文件,不跟业务耦合
  • test_case:测试用例
    • test_baidu:对应一个page,页面/模块的测试用例
  • test_report:
    • 运行生成的allure报告

二、实现的功能

  • 元素定位与业务操作分离
  • 失败重跑
  • 可配置有头无头浏览器等
  • 实现参数化读取数据文件
  • allure报告
  • 邮件发送

三、使用方式

3.1、安装依赖

pip3 install -r requirements.txt

使用allure的,安装allure

3.2、修改配置config.py文件

import os
from common.config import *
"""
运行测试配置
"""
class RunConfig:
    # 运行测试用例的目录或文件
    # cases_path = os.path.join(case_path, "test_case")
    cases_path = os.path.join(case_path, "test_baidu.py")
    # 配置浏览器驱动类型(chromium, firefox, webkit)。
    browser = "chromium"
    # 运行模式(headless, headful)
    # mode = "headless"
    mode = "headful"
    # 配置运行的 URL
    baseUrl = "https://www.baidu.com"
    # 失败重跑次数
    rerun = "0"
    # 当达到最大失败数,停止执行
    max_fail = "5"
    # 报告路径(不需要修改)
    NEW_REPORT = None

3.3、运行

python3 myRunner.py

3.4、查看报告

allure报告:test_report文件夹找html文件
trace日志:python3 -m playwright show-trace trace.zip

四、单个文件介绍

4.1、common-->config文件

存放的是配置,发送邮件的邮件信息、目录路径、

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
"""邮件配置"""
sender = ''  #发送方
receiver = '' #接收方
emailusername = ''  #登陆邮箱的用户名
emailpassword = ''  #登陆邮箱的授权码,客户端专用密码
server = ''  #smtp服务器
smtp_server_port = ''

#项目配置
basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# page目录
page_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'page')

# case目录
case_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'test_case')

#数据目录
data_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'data')

# 报告目录
report_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'test_report')

#日志目录
log_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'log')

# os.path.abspath(path) #返回绝对路径
# os.path.basename(path) #返回文件名
# os.path.dirname(path) #返回文件路径
# os.path.join(path1[, path2[, ...]])  #把目录和文件名合成一个路径

4.2、common-->log封装log,打印详细的日志信息

# coding=utf-8
import logging
import time
import os
from common.config import *

logname = os.path.join(log_path, '{0}.log'.format(time.strftime('%Y-%m-%d--%H_%M_%S')))

class Log:
    def __printconsole(self, level, message):
        """创建一个logger"""
        logger = logging.getLogger()
        logger.setLevel(logging.DEBUG)
        """创建一个handler,用于写入日志文件"""
        fh = logging.FileHandler(logname, 'a', encoding='utf-8')
        fh.setLevel(logging.DEBUG)
        """再创建一个handler,用于输出到控制台"""
        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        """定义handler的输出格式"""
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        """给logger添加handler"""
        logger.addHandler(fh)
        logger.addHandler(ch)
        """记录一条日志"""
        if level == 'info':
            logger.info(message)
        elif level == 'debug':
            logger.debug(message)
        elif level == 'warning':
            logger.warning(message)
        elif level == 'error':
            logger.error(message)
        logger.removeHandler(ch)
        logger.removeHandler(fh)
        """关闭打开的文件"""
        fh.close()

    def debug(self, message):
        self.__printconsole('debug', message)

    def info(self, message):
        self.__printconsole('info', message)

    def warning(self, message):
        self.__printconsole('warning', message)

    def error(self, message):
        self.__printconsole('error', message)

logger = Log()

4.3、page-->baidu抽离元素,单独存放元素

class BaiduElem:
    search_input = "#kw"  # 搜索框
    search_button = "#su"  # 搜索按钮
    settings = "#s-usersetting-top"  # 设置
    search_setting = "#s-user-setting-menu > div > a.setpref"  # 搜索设置
    save_setting = 'text="保存设置"'  # 保存设置

4.4、test_case-->test_baidu。模块/页面的用例操作,调用page页面的元素

import sys
from time import sleep
from playwright.async_api import Dialog
from seldom.testdata.conversion import json_to_list
from page.baidu import BaiduElem
import allure
import pytest
from common.config import  *

@allure.feature('百度测试')
class TestBaidu():

    @allure.story("test001-搜索")
    def test_baidu_001(self, page, base_url):
        """
        名称:百度搜索"playwright"
        步骤:
        1、打开浏览器
        2、输入"playwright"关键字
        3、点击搜索按钮
        检查点:
        * 检查页面标题是否相等。
        """
        page.goto(base_url)
        page.type(BaiduElem.search_input, text="playwright")
        page.click(BaiduElem.search_button)
        sleep(2)
        assert page.title() == "playwright_百度搜索"

    @allure.story("test002-保存设置")
    def test_baidu_002(self, page, base_url):
        """
        名称:百度搜索设置
        步骤:
        1、打开百度浏览器
        2、点击设置链接
        3、在下拉框中"选择搜索"
        4、点击"保存设置"
        5、对弹出警告框保存
        检查点:
        * 检查是否弹出提示框
        """
        page.goto(base_url)
        page.click(BaiduElem.settings)
        page.click(BaiduElem.search_setting)
        sleep(2)
        page.click(BaiduElem.save_setting)

        def on_dialog(dialog: Dialog):
            assert dialog.type == "alert"
            assert dialog.message == "已经记录下您的使用偏好"
            dialog.accept()

        page.on("dialog", on_dialog)


    @allure.story("test003-搜索中国")
    def test_baidu_003(self, page):
        page.goto("https://www.baidu.com/")
        # Click input[name="wd"]
        page.click("input[name=\"wd\"]")
        # Fill input[name="wd"]
        page.fill("input[name=\"wd\"]", "zhongguo ")
        # Press Enter
        # with page.expect_navigation(url="https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=zhongguo%20&fenlei=256&rsv_pq=d3b5747500073d0a&rsv_t=0df4UB%2Fe5SQx6iVzGFj5id3G0Ani1ItME5dWapeuAhqLKksg0aXPVl0A86k&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=10&rsv_sug1=7&rsv_sug7=100&rsv_sug2=0&rsv_btype=i&prefixsug=zhongguo%2520&rsp=5&inputT=1667&rsv_sug4=2346&rsv_jmp=fail"):
        with page.expect_navigation():
            page.press("input[name=\"wd\"]", "Enter")

    @pytest.mark.parametrize(
        "name, search_key",
        [("1", "Selenium"),
         ("2", "pytest文档"),
         ("3", "pytest-html"),
         ],
        ids=["case1", "case2", "case3"]
    )
    @allure.story("test004-参数化")
    def test_baidu_004(self, name, search_key, page, base_url):
        page.goto(base_url)
        page.type(BaiduElem.search_input, search_key)
        page.click(BaiduElem.search_button)
        sleep(2)
        assert page.title() == search_key + "_百度搜索"



    @pytest.mark.parametrize(
        "name, search_key",
        json_to_list(data_path + "/data_file.json")
    )
    @allure.story("test005-文件读取参数化")
    def test_baidu_006(self, name, search_key, page, base_url):
        page.goto(base_url)
        page.type(BaiduElem.search_input, search_key)
        page.click(BaiduElem.search_button)
        sleep(2)
        assert page.title() == search_key + "_百度搜索"

 

友情链接:第一篇:https://www.cnblogs.com/zhangxue521/p/17082166.html

 

posted @ 2023-02-02 15:29  爱笑的眼睛真美  阅读(316)  评论(1编辑  收藏  举报