软件测试|web自动化测试神器playwright教程(十)

简介: 软件测试|web自动化测试神器playwright教程(十)

前言

PO设计模式是我们在进行web自动化测试中经常使用到的思想和原则,甚至已经成为了web自动化测试的标准模型,PO设计模式在selenium官方文档中是被推荐的原则,同样的,playwright也是完全支持我们按照PO模式的思想来写我们的测试用例。

什么是PO?

PO,即Page Object,直译为页面对象,代表 Web 应用程序的一部分。以电子商务web程序为例,可能有一个主页、一个列表页面和一个结帐页面。这几个页面每一个都可以作为一个单独的page页面,页面对象通过创建适合您的应用程序的更高级别的 API 来简化创作,并通过在一个地方捕获元素选择器和创建可重用代码来避免重复来简化维护。

playwright PO模式的官方示例如下:

# models/search.py
class SearchPage:
    def __init__(self, page):
        self.page = page
        self.search_term_input = page.locator('[aria-label="Enter your search term"]')

    def navigate(self):
        self.page.goto("https://bing.com")

    def search(self, text):
        self.search_term_input.fill(text)
        self.search_term_input.press("Enter")

测试中使用页面对象

# test_search.py
from models.search import SearchPage

# in the test
page = browser.new_page()
search_page = SearchPage(page)
search_page.navigate()
search_page.search("search query")

PO应用实例

我们以常见的注册页面为例,如下图:

在这里插入图片描述
注册页面根据输入框的内容,我们可以写多个有效等价,无效等价的测试用例,那么这些用例的操作最终都是在页面上的几个固定元素上点点点。

在这里插入图片描述

整个项目结构

├─cases
│  │  test_register.py
│  │  __init__.py
├─models
│  │  register_page.py
│  │  __init__.py
│  │
├─conftest.py
├─pytest.ini

第一步,将注册页上的元素和操作封装成RegisterPage类,

from playwright.sync_api import Page


class RegisterPage:

    def __init__(self, page: Page):
        self.page = page
        self.locator_username = page.get_by_label("用 户 名:")
        self.locator_password = page.get_by_label("密     码:")
        self.locator_register_btn = page.locator('text=立即注册')
        self.locator_login_link = page.locator('text=已有账号?点这登录')
        # 用户名输入框提示语
        self.locator_username_tip1 = page.locator('[data-fv-validator="notEmpty"][data-fv-for="username"]')
        self.locator_username_tip2 = page.locator('[data-fv-validator="stringLength"][data-fv-for="username"]')
        self.locator_username_tip3 = page.locator('[data-fv-validator="regexp"][data-fv-for="username"]')
        # 密码输入框提示语
        self.locator_password_tip1 = page.locator('[data-fv-validator="notEmpty"][data-fv-for="password"]')
        self.locator_password_tip2 = page.locator('[data-fv-validator="stringLength"][data-fv-for="password"]')
        self.locator_password_tip3 = page.locator('[data-fv-validator="regexp"][data-fv-for="password"]')
        # 账号或密码不正确!
        self.locator_register_error = page.locator('text=用户名已存在或不合法!')

    def navigate(self):
        self.page.goto("http://xxx.x.x.x:8000/register.html")

    def fill_username(self, username):
        self.locator_username.fill(username)

    def fill_password(self, password):
        self.locator_password.fill(password)

    def click_register_button(self):
        self.locator_register_btn.click()

    def click_login_link(self):
        self.locator_login_link.click()

第二步,conftest.py 前置和后置操作代码

from playwright.sync_api import sync_playwright
import pytest


@pytest.fixture(scope="session")
def context_chrome():
    p = sync_playwright().start()
    browser = p.chromium.launch(headless=False)
    context = browser.new_context()
    yield context
    # 实现用例后置
    context.close()
    browser.close()
    p.stop()

第三步,用例部分代码

from models.register_page import RegisterPage
from playwright.sync_api import expect
import pytest


class TestRegister:

    @pytest.fixture(autouse=True)
    def start_for_each(self, context_chrome):
        print("for each--start: 打开新页面访问注册页")
        self.page = context_chrome.new_page()
        self.register = RegisterPage(self.page)
        self.register.navigate()
        yield
        print("for each--close: 关闭注册页")
        self.page.close()

    def test_register_1(self):
        """用户名为空,点注册"""
        self.register.fill_username('')
        self.register.fill_password('123456')
        self.register.click_register_button()
        # 断言
        expect(self.register.locator_username_tip1).to_be_visible()
        expect(self.register.locator_username_tip1).to_contain_text("不能为空")

    def test_register_2(self):
        """用户名大于30字符"""
        self.register.fill_username('hello world hello world hello world')
        # 断言
        expect(self.register.locator_username_tip2).to_be_visible()
        expect(self.register.locator_username_tip2).to_contain_text("用户名称1-30位字符")
        # 断言 注册按钮不可点击
        expect(self.register.locator_register_btn).not_to_be_enabled()

    def test_register_3(self):
        """用户名有特殊字符"""
        self.register.fill_username('hello!@#')
        # 断言
        expect(self.register.locator_username_tip3).to_be_visible()
        expect(self.register.locator_username_tip3).to_contain_text("用户名称不能有特殊字符,请用中英文数字")
        # 断言 注册按钮不可点击
        expect(self.register.locator_register_btn).not_to_be_enabled()

    def test_register_4(self):
        """密码框不能为空"""
        self.register.fill_username('hello')
        self.register.fill_password('')
        self.register.click_register_button()
        # 断言
        expect(self.register.locator_password_tip1).to_be_visible()
        expect(self.register.locator_password_tip1).to_contain_text("不能为空")

    @pytest.mark.parametrize('test_input', ['abc12', 'abc1234567890abc1'])
    def test_register_5(self, test_input):
        """密码框6-16位"""
        self.register.fill_password(test_input)
        # 断言
        expect(self.register.locator_password_tip2).to_be_visible()
        expect(self.register.locator_password_tip2).to_contain_text("密码6-16位字符")

    def test_register_6(self):
        """密码框不能有特殊字符"""
        self.register.fill_password('abc123!')
        # 断言
        expect(self.register.locator_password_tip3).to_be_visible()
        expect(self.register.locator_password_tip3).to_contain_text("不能有特殊字符,请用中英文数字下划线")

    def test_login_link(self):
        """已有账号?点这登录"""
        expect(self.register.locator_login_link).to_have_attribute("href", "login.html")
        self.register.click_login_link()
        expect(self.register.page).to_have_title('网站登录')

    def test_register_error(self):
        """测试注册正常流程, 已被注册过的账号"""
        self.register.fill_username('xxxx')
        self.register.fill_password('ab123456')
        self.register.click_register_button()
        # 断言提示语可见
        expect(self.register.locator_register_error).to_be_visible()

    def test_register_success(self):
        """测试注册正常流程, 注册成功"""
        # 生成随机账号
        import uuid
        self.register.fill_username(str(uuid.uuid4())[:8])
        self.register.fill_password('aa123456')
        self.register.click_register_button()
        # 断言提示语可见
        expect(self.register.page).to_have_title('首页')

总结

我们可以运行上述的测试用例,比较与selenium编写的PO脚本的速度,playwright对很多断言方法都有了封装,运行体验还是相当不错的。

相关文章
|
5天前
|
前端开发 机器人 测试技术
【RF案例】Web自动化测试弹窗处理
在进行Web自动化测试时,常会遇到不同类型的弹窗,如ajax、iframe、新窗口及alert/Confirm等。这些弹窗可通过Selenium进行定位与处理。其中,ajax弹窗直接定位处理;iframe需先选中再操作;新窗口类似iframe处理;而alert/Confirm则需特殊方法应对。在Robot Framework中,需先定义并获取窗口后使用特定关键字处理。此外,还有部分div弹窗需在消失前快速定位。希望本文能帮助大家更好地处理各类弹窗。
16 6
【RF案例】Web自动化测试弹窗处理
|
13天前
|
Java API Apache
从零到英雄的蜕变:如何用Apache Wicket打造你的第一个Web应用——不仅是教程,更是编程之旅的启航
【9月更文挑战第4天】学习Apache Wicket这一开源Java Web应用框架是一段激动人心的旅程。本文将指导你通过Maven搭建环境,并创建首个“Hello, World!”应用。从配置`pom.xml`到实现`HelloWorldApplication`类,再到`web.xml`的设置,一步步教你构建与部署简单网页。适合初学者快速上手,体验其简洁API与强大组件化设计的魅力。
13 1
|
19天前
|
测试技术
基于LangChain手工测试用例转Web自动化测试生成工具
该方案探索了利用大模型自动生成Web自动化测试用例的方法,替代传统的手动编写或录制方式。通过清晰定义功能测试步骤,结合LangChain的Agent和工具包,实现了从功能测试到自动化测试的转换,极大提升了效率。不仅减少了人工干预,还提高了测试用例的可维护性和实用性。
29 4
|
17天前
|
监控 测试技术 持续交付
Web2py 项目部署也太让人头疼了吧!但掌握这些,你就能轻松搞定自动化部署!
【8月更文挑战第31天】在现代软件开发中,高效的项目部署至关重要。针对 Web2py 框架,自动化部署不仅提升开发效率,还减少了人为错误。首先需设置版本控制、服务器环境及配置管理;其次利用 CI/CD 工具(如 Jenkins)实现自动构建、测试与部署;再者采用 Docker 容器化技术确保跨环境一致性;最后部署监控与日志记录工具保障系统稳定性。通过这些步骤,可显著优化 Web2py 项目的部署流程。例如,使用 Fabric 可简化部署脚本编写,实现服务器代码更新、依赖安装及服务重启等操作自动化。
22 1
|
17天前
|
Web App开发 测试技术 API
自动化测试之美:使用Selenium和Python进行Web应用测试
【8月更文挑战第31天】在软件开发的快节奏世界中,自动化测试如同一束明灯,照亮了质量保证之路。本文将引导你通过Selenium和Python的强大组合,探索如何构建高效的Web应用测试框架。我们不仅会讨论理论,还会深入代码,从一个简单的示例开始,逐步扩展至更复杂的场景。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用的技巧。让我们一同揭开自动化测试的神秘面纱,体验它的魅力所在。
|
3天前
|
jenkins 测试技术 持续交付
自动化测试的高效之路:如何利用Python进行Web应用测试
【9月更文挑战第13天】在软件开发的快节奏中,自动化测试是确保质量和效率的关键。本文将引导你了解如何使用Python语言及其强大的测试框架来提升Web应用的测试效率。我们将一起探索编写简洁而强大的测试脚本的技巧,以及如何通过持续集成(CI)实现自动化测试流程。准备好让你的测试工作飞一般的感觉!
|
16天前
|
数据库 开发者 Python
web应用开发
【9月更文挑战第1天】web应用开发
33 1
|
4天前
|
数据可视化 图形学 UED
只需四步,轻松开发三维模型Web应用
为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
24 8
只需四步,轻松开发三维模型Web应用
|
13天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
14天前
|
前端开发 JavaScript 持续交付
Web应用开发的方法
Web应用开发的方法
13 1