使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 32--开源电商商城系统项目实战--如何区分登录状态

测试学习记录,仅供参考!

项目实战 5(开源电商商城系统项目)

登录状态

如何区分用户是否已经登录?这里通过在前置操作中去实现,通过传入不同的前置应用操作来此区分登录和非登录的状态;

例如在大部分电子商务商城的应用系统或者需要进行用户身份认证的在线系统中,一个客户与服务器经常经过好几次的交互过程才能完成一笔交易订单或者是一个请求的完成;由于这其中几次交互过程是密切相关的,服务器在进行这些交互过程的某一个交互步骤时往往需要了解上一次或上几次的交互过程处理结果,这就要求所有这些相关的交互过程一般都由一台服务器完成;

在有些要求登录状态的测试场景中,某些情景是要求客户端和服务器之间保持一个会话以记录客户端的各种信息;这里的登录状态是指在 web ui 自动化测试时通过账号和密码的方式来保持会话登录状态的,与平常的 HTTP(HTTPS) 请求中 cookies、session、token 等无必要关系;

cookies:cookie 是一种客户端会话跟踪技术,它将数据存储在客户端浏览器中;通过使用 cookie,可以在浏览器第一次发起请求时,在服务器端设置一个 cookie;cookie 是服务器传递到浏览器,保存在浏览器中的数据,然后浏览器每次请求都带上 cookie,这样就可以标识用哪一个用户发起的请求;

session:session 是一种在服务器端存储用户会话信息的技术,用于在多个请求之间保持用户的状态;session 是把用户的信息保存在服务器上面, 浏览器第一次访问的时候服务器把 sessionID 传递到浏览器,然后浏览器把 Session_id 保存在 cookie 中, 每次访问把 session_id 带上,服务器就可以标识这个请求来自于那个用户,然后根据 session_id 查这个这个用户的 seesion 里面记录了哪些数据,这种方式可以提高数据的安全性和可靠性;

token:当客户端第一次请求会话,发送用户信息到服务端,服务器对用户信息使用加密算法以及密钥进行签名,再将这个签名和数据一次作为 token 返回给客户端,一般情况下服务端不保存 token,由客户端保存 token,当客户端再次请求的话,会将 token 发送给服务端,服务端同样用加密算法和同样的密钥对数据再一次计算签名,和之前 token 中的签名做比较,只要有一个通过了验证,数据信息和资源就能够在任何域上被请求到;在 web 领域中基于 token 的身份验证比较常见,在大多数使用 web API 的互联网应用中,token 是多用户下处理认证的最佳方式;

改造前置应用

1、优化项目根目录 testcase 软件包下 conftest.py 文件(前置操作文件),增加登录状态前置操作应用、非登录状态前置应用操作;

复制代码
import pytest
from selenium import webdriver
from util_tools.logs_util.recordlog import logs
from config.setting import browser_type, WAIT_TIME
from pageObject.login_page.login_page import LoginPage

@pytest.fixture(autouse=True)
def log_outputs():
    logs.info('------测试用例开始执行testcase------')
    yield
    logs.info('------测试用例执行完毕testcase------')


# @pytest.fixture()
# def get_driver():
#     # 将driver设置为全局变量
#     global driver
# 
#     #  初始化浏览器对象--字典
#     browser_mapping = {
#         'Chrome': webdriver.Chrome,
#         'Edge': webdriver.Edge,
#         'Firefox': webdriver.Firefox
#     }
# 
#     # 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
#     if browser_type.capitalize() in browser_mapping:
#         driver = browser_mapping.get(browser_type.capitalize())()
# 
#     # 设置一个全局的隐式等待时间
#     driver.implicitly_wait(WAIT_TIME)
#     # 最大化浏览器窗口
#     driver.maximize_window()
#     yield driver
#     driver.quit()


def init_driver():
    #  初始化浏览器对象--字典
    browser_mapping = {
        'Chrome': webdriver.Chrome,
        'Edge': webdriver.Edge,
        'Firefox': webdriver.Firefox
    }

    # 判断配置文件 browser_type 变量值包含在 browser_mapping 字典里面
    if browser_type.capitalize() in browser_mapping:
        return browser_mapping.get(browser_type.capitalize())()


@pytest.fixture(scope='class')
def get_driver():
    driver = init_driver()
    # 设置一个全局的隐式等待时间
    driver.implicitly_wait(WAIT_TIME)
    # 最大化浏览器窗口
    driver.maximize_window()
    yield driver
    driver.quit()


# 登录状态的前置应用
@pytest.fixture(scope='class')
def login_driver(get_driver):
    driver = get_driver
    login_page = LoginPage(driver)
    # 自行设置是否参数化
    login_page.login('admin123', '123456')
    return driver


# 未登录状态的前置应用
@pytest.fixture()
def not_login_driver():
    driver = init_driver()
    # 设置一个全局的隐式等待时间
    driver.implicitly_wait(WAIT_TIME)
    # 最大化浏览器窗口
    driver.maximize_window()
    yield driver
    driver.quit()

2、如登录测试用例需要用到未登录时的前置操作,可以使用未登录时的前置功能;

3、优化 testcase 软件包 login 目录下 test_login.py 文件;

更改 get_driver 为 not_login_driver;

复制代码
import pytest
from selenium.webdriver.common.by import By
from time import sleep
from pageObject.login_page.login_page import LoginPage
from util_tools.handle_data.operateJson import read_json

class TestLogin:

    # 登录成功
    # @pytest.mark.run(order=1)   # 指定先运行
    # 使用参数化实现一条测试用例跑多种场景--可迭代对象里面有多少组数据就跑多少次测试用例
    @pytest.mark.parametrize('data', read_json('./data/login_success.json'))
    # 用一个 data(需与上面保持一致) 参数去接收参数化数据
    def test_login_success(self, not_login_driver, data):
        # 进行列表解包--通过两个参数去接收列表中的数据
        username, password = data
        # 传浏览器对象--再把结果返回
        login_page = LoginPage(not_login_driver)
        # 直接调用页面类中的 login 操作--里面需要输入两个参数(参数化传两个参数)
        login_page.login(username, password)
        # 断言结果
        login_page.assert_is_element_present(login_page.assert_result)
        sleep(2)

    # 登录失败
    @pytest.mark.parametrize('data', read_json('./data/login_failed.json'))
    def test_login_failed(self, not_login_driver, data):
        username, password = data
        login_page = LoginPage(not_login_driver)
        login_page.login(username, password)
        login_page.assert_title('系统提示')
        sleep(2)

4、如提交订单测试用例需要用到登录状态下的前置操作;

5、 优化 testcase 软件包 flow 目录下 test_flow.py 文件;

更改 get_driver 为 login_driver;

复制代码
# 导包
from pageObject.flow_page.flow_page import FlowPage
from time import sleep

class TestFlow:

    # 失败场景,购物车没有商品时
    def test_purchase_failure(self, login_driver):
        flow_page = FlowPage(login_driver)
        flow_page.flow_failed()
        # 断言没有商品时跳转的url页面地址
        assert flow_page.current_url == 'http://localhost:8088/ecshop/flow.php?step=checkout'
        sleep(3)

    # 成功操作,购物车有商品
    def test_purchase_success(self, login_driver):
        flow_page = FlowPage(login_driver)
        flow_page.flow_success()
        # 订单提交成功,断言url
        assert flow_page.current_url == 'http://localhost:8088/ecshop/flow.php?step=done'
        sleep(3)

6、注册测试用例需要用到未登录时的前置操作;

7、优化 testcase 软件包 register 目录下 test_register.py 文件;

更改 get_driver 为 not_login_driver;

复制代码
# 导包
from pageObject.register_page.register_page import RegisterPage
import pytest
from time import sleep
from util_tools.handle_data.readYaml import read_yaml

class TestRegister:

    # 注册成功场景
    @pytest.mark.parametrize('data', read_yaml('./data/register_success.yaml'))
    def test_register_success(self, not_login_driver, data):
        # 调用页面类相关的操作--直接调用RegisterPage()把浏览器对象get_driver传给它
        register_page = RegisterPage(not_login_driver)
        # 如果使用 *data 解包数据,data的元素数量必须跟click_register方法的入参个数保持一致
        register_page.click_register(*data)
        # 添加等待时间查看效果
        sleep(3)
        # 断言结果
        register_page.assert_is_element_present(register_page.assert_result)

    # 注册失败场景
    @pytest.mark.parametrize('data', read_yaml('./data/register_failed.yaml'))
    def test_register_failed(self, not_login_driver, data):
        register_page = RegisterPage(not_login_driver)
        register_page.click_register(*data)
        sleep(3)
        register_page.assert_element_not_visible(register_page.assert_result)

    # 跳转链接--只是一个按钮,不需要参数化
    def test_check_skip_login(self, not_login_driver):
        register_page = RegisterPage(not_login_driver)
        register_page.skip_login_page()
        # 断言结果--直接断言页面url
        assert register_page.current_url == 'http://localhost:8088/ecshop/user.php?act=login'

8、 运行测试调试,可以发现提交订单还是没有运行成功,在没有商品的时候,进入不到收货人信息填写、提交订单页面,缺少把商品加入购物车操作;

一个测试用例(页面类)中写多个页面

把商品加入购物车页面

9、在项目根目录 pageObject 软件包 flow_page 目录文件下新建名称一个为 search_page.py 的 Python 文件;把商品加入"购物车"页面;

在首页先点击高级搜索按钮;高级搜索关键字→立即搜索→商品搜索成功出来之后购买

复制代码
# 导包
from selenium.webdriver.common.by import By
from util_tools.basePage import BasePage
from time import sleep

class SearchPage(BasePage):
    url = '/search.php'
    # 高级搜索按钮
    advanced_search = (By.LINK_TEXT, '高级搜索')
    # 关键字搜索框
    keywords = (By.NAME, 'keywords')
    # 立即搜索按钮
    submit = (By.NAME, 'Submit')
    # 购买按钮
    buy_button = (By.LINK_TEXT, '购买')

    def add_cart(self):
        """
        点击购买按钮将商品加入购物车中
        :return:
        """
        self.open_url(self.url)
        # 点击高级搜索
        self.click(self.advanced_search)
        # 搜索框输入数据
        self.send_keys(self.keywords, '测试商品抽纸类')
        # 点击立即搜索按钮
        self.click(self.submit)
        sleep(3)
        # 商品搜索出来之后点击购买按钮
        self.click(self.buy_button)

10、封装完成之后在 test_flow.py 文件中使用(一个测试用例里面使用两个页面类);

复制代码
# 导包
from pageObject.flow_page.flow_page import FlowPage
from pageObject.flow_page.search_page import SearchPage
from time import sleep

class TestFlow:

    # 失败场景,购物车没有商品时
    def test_purchase_failure(self, login_driver):
        flow_page = FlowPage(login_driver)
        flow_page.flow_failed()
        # 断言没有商品时跳转的url页面地址
        assert flow_page.current_url == 'http://localhost:8088/ecshop/flow.php?step=checkout'
        sleep(3)

    # 成功操作,购物车有商品
    def test_purchase_success(self, login_driver):
        # 先将商品加入购物车
        search_page = SearchPage(login_driver)
        search_page.add_cart()
        # 去结算中心提交订单
        flow_page = FlowPage(login_driver)
        flow_page.flow_success()
        # 订单提交成功,断言url
        assert flow_page.current_url == 'http://localhost:8088/ecshop/flow.php?step=done'
        sleep(3)

11、设置测试数据(data 目录文件下相关文件),运行主函数 run.py 文件,可以运行成功;

未完待续。。。

相关推荐
ZAz_14 小时前
DAY 38 模型可视化与推理
python
艾上编程14 小时前
第二章——数据分析场景之用Python进行CSV/Excel数据清洗:为数据分析筑牢根基
python·数据分析·excel
闲人编程14 小时前
FastAPI性能优化技巧
后端·python·性能优化·fastapi·性能·codecapsule
Amazon数据采集14 小时前
# 🚀 亚马逊URL参数拼接实战:数据采集效率提升指南
python
岁月宁静14 小时前
FastAPI 入门指南
人工智能·后端·python
AI小云14 小时前
【数据操作与可视化】Serborn绘图-类别散点图和热力图
python·数据可视化
码界奇点15 小时前
基于Python与Django的白泽自动化运维系统设计与实现
运维·python·django·毕业设计·源代码管理
semantist@语校15 小时前
第五十五篇|从解释约束到结构化认知:京都国际学院的语言学校Prompt工程化实践
大数据·数据库·人工智能·python·百度·prompt·知识图谱
我送炭你添花15 小时前
Pelco KBD300A 模拟器:05.校验算法终极对比 + 完整 100+ 指令封装 + KBD300A 所有隐藏功能函数化
python·算法·自动化·运维开发