软测入门(八)Selenium项目实战

news2025/7/22 23:43:46

自动化项目实战

项目计划设计

  • 测试计划
  • 测试范围
  • 设定目标
  • 规划活动

实际项目中,需要根据项目的实际情况创建自己的项目计划,没有固定的格式和内容要求:

项目简介自动化实现网上购票
项目启动前置条件1.购票网站工作正常 2.自动化测试环境准备完毕(Python Selenium3.0 谷歌驱动下载完毕)
覆盖场景场景的确定需要根据性能需求分析得出,需要多方人员参与,开发、测试、产品等
1.火车票查询页面
2.车次列表页面
3.账号登录界面
4.订单信息页面

测试用例设计

在这里插入图片描述

仅作参考,实际项目按照要求设计即可。

自动化测试脚本

例如:要进行买票四次,那么准备一个数据文件
在这里插入图片描述

脚本开发及代码优化

可分三层:

  • 测试代码层 测试
  • 业务代码层 业务
  • 基础代码层 准备环境

基础层base_function.py,需要从excel中读取数据,然后测试多次。

# @creator by wlh
# @date 2023/3/7 9:51
from datetime import date, timedelta
from selenium import webdriver
from selenium.webdriver.common.by import By
import xlrd

# 计算日期 n=1时,表示是 明天
def date_n(n):
    return str(date.today() + timedelta(days=int(n)))

# 获取浏览器驱动(后面多次测试,只用这一个driver)
driver = webdriver.Chrome()

# 根据 name查询
def name(element_name):
    return driver.find_element(By.NAME, element_name)

# 根据xpath查询
def xpath(xpath):
    return driver.find_element(By.XPATH, xpath)

# 打开网址
def open_url(url):
    driver.get(url)
    driver.maximize_window()

# 获取driver,每次只返回同一个driver,如果是不同的driver,那么会打开多个浏览器  注意!!!
def get_driver():
    return driver

# 读取excel数据
def read_excel(filename, hasHead = False):
    # 打开工作簿
    xlsx = xlrd.open_workbook(filename)
    # 获取第一个sheet页对象
    sheet = xlsx.sheet_by_index(0)
    data = []
    for i in range(sheet.nrows):
        # 对标题的处理,是否添加到 列表 中
        if i == 0 and not hasHead:
            continue
        data.append(sheet.row_values(i))
    print(data)
    return data

业务层代码quna_book.py,当需要多次执行业务层代码时,浏览器驱动不需要使用 close()或quit(),否则的话只能执行一次流程!!!

# @creator by wlh
# @date 2023/3/7 9:52
import time

from selenium.webdriver import ActionChains, Keys
from base_function import *


def book_ticket(start, end, n, cartName, cartNo):
    driver = get_driver()
    open_url("https://train.qunar.com/")
	# 避免元素未加载出来
    time.sleep(1)
    action = ActionChains(driver)
    # 多次测试时,需要先清除上一次的内容
    name("fromStation").clear()
    name("fromStation").send_keys(start)
    time.sleep(0.5)
    # 移动位置 点击一下
    action.move_by_offset(0, 0)
    action.click()
    action.perform()

    # 多次测试时,需要先清除上一次的内容
    name("toStation").clear()
    name("toStation").send_keys(end)
    time.sleep(0.5)
    # 移动位置 点击一下
    action.move_by_offset(0, 0)
    action.click()
    action.perform()

    # 日期先清除之前的数据,然后再填写
    name("date").send_keys(Keys.CONTROL, "a", Keys.BACKSPACE)

    # 计算日期
    dateCome = date_n(n)

    name("date").send_keys(dateCome)
    # 移动位置 点击一下
    action.move_by_offset(0, 0)
    action.click()
    action.perform()

    # 点查询 车次
    name("stsSearch").click()
    # 等待页面一些元素的加载
    time.sleep(1)

    # 选择第一个车次,购买即可
    xpath("//*[@id='list_listInfo']/ul[2]/li[1]/div/div[7]/a[1]").click()
    # 等待页面一些元素的加载
    time.sleep(1)

    name("pName_0").send_keys(cartName)
    name("pCertNo_0").send_keys(cartNo)

    time.sleep(2)

测试层代码test_book.py

# @creator by wlh
# @date 2023/3/7 9:52
from quna_book import book_ticket
from base_function import read_excel
import pytest

# 读取 excel
data = read_excel("../data.xlsx")

# 采用 pytest的参数化,执行多次测试流程
@pytest.mark.parametrize(["start", "end", "n", "name", "no"], data)
def test_boo_ticket(start, end, n, name, no):
    book_ticket(start, end, n, name, no)

# pytest测试
if __name__ == '__main__':
    pytest.main(["-s", "test_book.py"])

PO模式处理!!

PO模式: Page Object,把页面当成对象;把页面中的业务放到其他

优点:

  • 页面分层 页面元素 和业务逻辑进行区分
  • 方便复用对象
  • 每个页面都是一个独立的测试用例
  • 自动化变得更加容易

base层: ----> 基础内容

common层: ----> 读取文件、日期处理、公共的

data层: ----> 数据的文件

logs层: ------> 日志

PO层: --------> 页面的业务代码

testcase: ------> 测试层的代码

reports: ------> 存放测试报告

config: --------> 配置文件

目录结构

在这里插入图片描述

base层代码base.py

通常情况下代码无提示,那么可以使用 # type: 类的方式告知解释器变量的类型,且代码会有提示

# @creator by wlh
# @date 2023/3/7 11:12
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.common.by import By

class Base:
    def __init__(self, driver):
        self.driver = driver  # type: WebDriver

    # 根据 name查询
    def name(self, element_name):
        return self.driver.find_element(By.NAME, element_name)

    # 根据xpath查询
    def xpath(self, xpath):
        return self.driver.find_element(By.XPATH, xpath)

    # 打开网址
    def open_url(self, url):
        self.driver.get(url)
        self.driver.maximize_window()

    # 关闭窗口
    def close(self):
        self.driver.close()

common层代码function.py

# @creator by wlh
# @date 2023/3/7 11:10

from datetime import date, timedelta
import xlrd
# 读取excel数据
def read_excel(filename, hasHead=False):
    xlsx = xlrd.open_workbook(filename)
    sheet = xlsx.sheet_by_index(0)
    data = []
    for i in range(sheet.nrows):
        if i == 0 and not hasHead:
            continue
        data.append(sheet.row_values(i))
    return data


# 计算日期 n=1时,表示是 明天
def date_n(n):
    return str(date.today() + timedelta(days=int(n)))

data层就放一个excel文件即可。

po层,可以根据页面的数量,创建多个po文件,如此项目共跳转3个页面,那么整3个文件封装下即可。

book_ticket_page.py买票查询页面

# @creator by wlh
# @date 2023/3/7 11:18
import time
from selenium.webdriver import ActionChains, Keys
from ..base.base import Base

# 购票 PO
class BookTicket(Base):

    # 起始地
    def book_start(self):
        return self.name("fromStation")
	# 目的地
    def book_end(self):
        return self.name("toStation")
	# 查询按钮
    def book_button(self):
        return self.name("stsSearch")
	# 移动点击 (防止元素被遮盖)
    def move_click(self):
        action = ActionChains(self.driver)
        action.move_by_offset(0, 0)
        action.click()
        action.perform()
	# 出发日期
    def book_date(self, date):
        self.name("date").send_keys(Keys.CONTROL, "a", Keys.BACKSPACE)
        self.name("date").send_keys(date)

    # 查询具体动作
    def book_ticket(self, start, end, date):
        self.book_start().clear()
        self.book_start().send_keys(start)
        time.sleep(0.5)
        # 移动位置 点击一下
        self.move_click()

        self.book_end().clear()
        self.book_end().send_keys(end)
        time.sleep(0.5)
        # 移动位置 点击一下
        self.move_click()

        # 日期先清除之前的数据,然后再填写
        self.book_date(date)
        # 移动位置 点击一下
        self.move_click()

        # 点查询 车次
        self.book_button().click()
        time.sleep(1.5)

book_list_page.py车次列表页面

# @creator by wlh
# @date 2023/3/7 11:33
import time
from selenium_test.qunapo.base.base import Base

class BookList(Base):
    # 购买按钮
    def book_buy(self):
        return self.xpath("//*[@id='list_listInfo']/ul[2]/li[1]/div/div[7]/a[1]")
	# 具体购买流程
    def book_list(self):
        self.book_buy().click()
        time.sleep(2)

book_order_page.py订票详情页

# @creator by wlh
# @date 2023/3/7 11:35
import time
from selenium_test.qunapo.base.base import Base

class BookOrder(Base):
	# 订票人
    def book_name(self):
        return self.name("pName_0")
	# 身份证号
    def book_no(self):
        return self.name("pCertNo_0")
	# 输入信息
    def book_order(self, cartName, cartNo):
        self.book_name().send_keys(cartName)
        self.book_no().send_keys(cartNo)
        time.sleep(1)

testcase测试层

# @creator by wlh
# @date 2023/3/7 11:38
import time
import pytest
from selenium import webdriver
from selenium_test.qunapo.po.book_ticket_page import BookTicket
from selenium_test.qunapo.po.book_list_page import BookList
from selenium_test.qunapo.po.book_order_page import BookOrder
from selenium_test.qunapo.common.function import read_excel, date_n
# 读取数据
data = read_excel("../data/data.xlsx")

class Test_Book:
	# 前置夹具
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://train.qunar.com/")
        self.driver.maximize_window()
        time.sleep(1)
	# 类后置夹具
    def teardown(self):
        self.driver.quit()
	# pytest参数化执行测试流程
    @pytest.mark.parametrize(["start", "end", "n", "name", "no"], data)
    def test_01(self, start, end, n, name, no):
        ticket = BookTicket(self.driver)
        # 查询票
        ticket.book_ticket(start, end, date_n(n))
        list = BookList(self.driver)
        # 车次列表页
        list.book_list()
        order = BookOrder(self.driver)
        # 输入乘客信息
        order.book_order(name, no)

if __name__ == '__main__':
    pytest.main(["-s", "test_book.py"])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA的16 个实用代码优化小技巧

一、类成员与方法的可见性最小化 举例:如果是一个private的方法,想删除就删除。 如果一个public的service方法,或者一个public的成员变量,删除一下,不得思考很多。 二、使用位移操作替代乘除法 计算机是使用二进制…

垒骰子(爆搜/DP)

动态规划方格取数垒骰子方格取数 题目描述 设有 NNN \times NNN 的方格图 (N≤9)(N \le 9)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 000。如下图所示(见样例): A0 0 0 0 0 0 0 00 0 13 0 …

ChatGPT助力校招----面试问题分享(一)

1 ChatGPT每日一题:期望薪资是多少 问题:面试官问期望薪资是多少,如何回答 ChatGPT:当面试官问及期望薪资时,以下是一些建议的回答方法: 1、调查市场行情:在回答之前,可以先调查一…

Python基础之while循环

一:while语法 while 条件:代码1 代码2 代码3....while的运行步骤: 步骤1:如果条件为真,那么依次执行:代码1、代码2、代码3、...... 步骤2:执行完毕后再次判断条件,如果条件为True则再次执行&#…

通用缓存存储设计实践

目录介绍 01.整体概述说明 1.1 项目背景介绍1.2 遇到问题记录1.3 基础概念介绍1.4 设计目标1.5 产生收益分析 02.市面存储方案 2.1 缓存存储有哪些2.2 缓存策略有哪些2.3 常见存储方案2.4 市面存储方案说明2.5 存储方案的不足 03.存储方案原理 3.1 Sp存储原理分析3.2 MMKV存储…

【数据挖掘】4、关联分析:Apriori、FP-Growth 算法、买面包是否也爱买啤酒

文章目录一、概念1.1 支持度1.2 置信度1.3 提升度二、Apriori 算法2.1 频繁项集的定义2.2 算法工作原理三、FP-Growth 算法3.1 算法步骤3.1.1 创建项头表3.1.2 构造 FP 树3.1.3 通过 FP 树挖掘频繁项集3.2 手动推导3.2.1 计算单一项的频率(支持度计数)3.…

shusheng007编程手记

[版权申明] 非商业目的注明出处可自由转载 出自:shusheng007 文章目录概述工具篇IntelliJ IDEA在Idea中下载源码时,报无法下载源码PostmanPost请求被识别成Get请求Linux开启关闭防火墙开放端口关闭端口如何修复磁盘Nginx如何使用docker来安装Nginx概述 …

VMware虚拟网络编辑桥接/NAT/仅主机模式详解

VMware虚拟网络编辑 安装VMware后 默认虚拟网络设置: VMnet0:桥接模式 VMnet1:仅主机 VMnet8:NAT模式 可以打开VMware的虚拟网络适配器查看 NAT模式 NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网…

掌握Swagger3自动化生成接口文档完成后端提效

文章目录OpenApi规范Swagger3快速上手Swagger3使用Swagger3.x常用注解讲解和配置Api 模块配置ApiOperation 接口配置ApiParam 方法参数配置ApiIgnore 忽略此接口ApiModel()和ApiModelProperty()ApiResponse描述接口响应注意可能出现的问题OpenApi规范 开放API规范(…

Java内存屏障简介

简介 内存屏障是插入两个CPU命令之间的命令,禁止处理器命令的重新排序(如屏障),以确保有序性。此外,为了达到屏障的效果,在处理器写入、读取值之前,将主机的值写入缓存,清空无效的队列,保障可见…

C++函数重载及其背后的原理

写在前面 先说说我的状态吧,五一假期五天假,这些天都在玩,很少学习,我不是后悔,也没必要,本来假期就是为了让自己放松.我唯一要反思看到别人在学,我心里也想学但是却做不到,这是我的缺点,后面我会克服的.尽…

运维提质增效,有哪些办法可以做

凡是代码,难免有 bug。 开发者们的日常,除了用一行行代码搭产品外,便是找出代码里的虫,俗称 debug。 随着移动互联网的快速发展,App 已经成为日常生活中不可或缺的一部分。但是在开发者/运维人员的眼里简直就是痛苦的…

使用R语言包clusterProfiler做KEGG富集分析时出现的错误及解决方法

使用enrichKEGG做通路富集分析时&#xff0c;一直报错&#xff1a;显示No gene can be mapped....k <- enrichKEGG(gene gene, organism "hsa", pvalueCutoff 1, qvalueCutoff 1)但是之前用同样的基因做分析是能够成功地富集到通路&#xff0c;即便是网上的数据…

Appium+Python连接真机、跳过登录页、Unexpected error while obtaining UI hierarchy问题

Appium连接真机 使用数据线连接电脑&#xff0c;然后选择文件传输方式 打开手机设置拉至底部&#xff0c;点击关于手机&#xff0c;连续点击7次版本号打开开发者模式 点击设置中的系统与更新&#xff0c;找到开发者选项----> 打开USB调试即可 在终端中输入adb devices确定…

c语言经典例题-数组的使用

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 选择法排序&#xff1a; 题目&#xff1a; 本关任务&#xff1a;使用选择法排序&#xff08;http://t.csdn.cn/…

统计学 一元线性回归

统计学 一元线性回归 回归&#xff08;Regression&#xff09;&#xff1a;假定因变量与自变量之间有某种关系&#xff0c;并把这种关系用适当的数学模型表达出来&#xff0c;利用该模型根据给定的自变量来预测因变量 线性回归&#xff1a;因变量和自变量之间是线性关系 非线…

看板组件:Bryntum Task Board JS 5.3.0 Crack

一个超级灵活的看板组件&#xff0c;Bryntum Task Board 是一个灵活的看板 Web 组件&#xff0c;可帮助您可视化和管理您的工作。 功能丰富 任务板非常灵活&#xff0c;允许您完全自定义卡片、列和泳道的渲染和样式。借助丰富的 API&#xff0c;您甚至可以在运行时打开或关闭功…

MSE 诊断利器上线

作者&#xff1a;子葵 背景 在日常开发和生产环境中&#xff0c;可能会遇到由于网络或者其他因素导致客户端连接 MSE 集群出现异常&#xff0c;此时需要排查集群以及客户端状态&#xff0c;通常需要通过文档查询对应的异常解释来定位问题&#xff0c;排查问题的链路比较长&am…

JNI内通过参数形式从C/C++中传递string类型数据至Java层

目录 0 前言 1 string类型参数形式传值 2 测试和结果 0 前言 类似之前我写过的两篇文章&#xff1a;一篇介绍了在JNI中基础类型int的传值方式&#xff1b;一篇详细梳理了在JNI层中多维数组的多种传值方式。 JNI内两种方式从C/C中传递一维、二维、三维数组数据至Java层详细…

如何实现接口幂等性

1 什么是幂等 幂等操作的特点是一次或者任意多次执行所产生的影响均与一次执行的影响相同&#xff0c;不会因为多次的请求而产生不一样的结果。换句话说&#xff0c;就是我使用相同的请求参数&#xff0c;去请求同一个接口&#xff0c;不管请求多少次获取到的响应数据应该是一…