自动化项目实战
项目计划设计
- 测试计划
- 测试范围
- 设定目标
- 规划活动
实际项目中,需要根据项目的实际情况创建自己的项目计划,没有固定的格式和内容要求:
项目简介 | 自动化实现网上购票 |
---|---|
项目启动前置条件 | 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"])