【UI自动化测试】2_PO模式 _单元测试框架(重点)

文章目录

一、单元测试框架

pytest(组织测试用例、方便生成测试报告、自动断言)

python 复制代码
python: unittest
java: junit、testNg

二、pytest组织测试用例

python 复制代码
"""
1、一个测试类对标手工测试用例的一个测试点(测试点有正反向)
2、每个具体用例标题对标手工用例中一个用例标题
3、类级别的初始化方法setup_class在整个测试类运行之前会运行一次
4、类级别的销毁的方法teardown_class在整个测试类运行完之后运行一次
5、函数级别的初始化方法setup在每个测试方法运行之前都会运行一次
"""

引入pytest的好处:   
- 方便组织、 管理多个测试用例
- 提供了丰富的断言方法
- 方便生成测试报告
- 减少了代码冗余  


存在的问题:  
- 代码冗余  
- 业务脚本与页面对象没有分开

常见问题
- 测试方法就是测试标题,对应的输入的测试数据一定要对应
- 运行测试用例,如选择单个测试方法运行则只会运行一条
- 运行时不是用的pytest单元测试框架运行,运行连浏览器都不会打开
  -- 第一:删除pycharm历史运行记录
  -- 第二:修改pycharm默认运行测试工具


version_02 (包)
- __init__.py
- test_login.py   #一个登录测试多种场景,写在一个测试文件当中,文件以test开头
- test_address.py # 测试新增地址

2.1 test_login.py

python 复制代码
# 导包
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

# 1、定义测试类 --->模块(登录模块)
class TestLogin():

    # 开始执行测试之前只会打开一次浏览器
    def setup_class(self):
        # 加self的意义:定义实例属性或者类属性,里面的实例方法或者类方法都可以访问
        # self表示当前类属性
        self.driver = webdriver.Chrome()
        # 后面访问驱动对象使用self.driver访问
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    # 所有的测试用例都运行完毕才会关闭浏览器
    def teardown_class(self):
        sleep(2)
        self.driver.quit()

    # 每个测试方法的起点一致;那么证明每个测试方法运行之前都会回到首页
    def setup(self):
        self.driver.get("https://hmshop-test.itheima.net/")

    # 2、定义测试方法 ---> 标题
    # 登录失败-(账户不存在)
    def test_login_account_not_exist(self):
        # 4、暂停3s ->代替测试步骤
        # a。使用Xpath 文本定位策略定位登录超链接,并点击
        self.driver.find_element_by_xpath("//*[text()='登录']").click()
        # b。使用Xpath 属性定位策略定位用户名输入框,并输入13600001111
        self.driver.find_element_by_xpath("//*[@id='username']").send_keys("13611111111")
        # c。使用Xpath  属性包含定位策略定位密码输入框,并输入123456
        self.driver.find_element_by_xpath("//*[contains(@id,'pass')]").send_keys("123456")
        # d。使用Xpath  属性与逻辑结合策略定位验证码输入框,并输入8888
        self.driver.find_element_by_xpath('//*[@placeholder="验证码" and @id="verify_code"]').send_keys("8888")
        # e。使用Xpath 层级与属性结合策略定位登录按钮,并点击;
        self.driver.find_element_by_xpath("//*[@class='login_bnt']/a").click()
        sleep(2)
        # 获取实际结果:
        msg = self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
        print("msg:", msg)
        # 判断实际结果和预期结果是否一致
        assert msg == "账号不存在!"


    # 登录失败-(密码错误)
    def test_login_password_error(self):
        # 4、暂停3s ->代替测试步骤
        # a。使用Xpath 文本定位策略定位登录超链接,并点击
        self.driver.find_element_by_xpath("//*[text()='登录']").click()
        # b。使用Xpath 属性定位策略定位用户名输入框,并输入13600001111
        self.driver.find_element_by_xpath("//*[@id='username']").send_keys("13600001111")
        # c。使用Xpath  属性包含定位策略定位密码输入框,并输入123456
        self.driver.find_element_by_xpath("//*[contains(@id,'pass')]").send_keys("error")
        # d。使用Xpath  属性与逻辑结合策略定位验证码输入框,并输入8888
        self.driver.find_element_by_xpath('//*[@placeholder="验证码" and @id="verify_code"]').send_keys("8888")
        # e。使用Xpath 层级与属性结合策略定位登录按钮,并点击;
        self.driver.find_element_by_xpath("//*[@class='login_bnt']/a").click()
        sleep(2)
        # 获取实际结果
        msg = self.driver.find_element(By.CSS_SELECTOR, ".layui-layer-content").text
        print("msg:", msg)
        # 断言,期望的提示信息包含在实际结果中
        assert "密码错误" in msg

2.2 test_address.py

python 复制代码
# 导包
import time
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait


class TestAddress:
    # 开始执行测试之前只会打开一次浏览器
    def setup_class(self):
        # 加self的意义:定义实例属性或者类属性,里面的实例方法或者类方法都可以访问
        # self表示当前类属性
        self.driver = webdriver.Chrome()
        # 后面访问驱动对象使用self.driver访问
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)
        self.driver.get("https://hmshop-test.itheima.net/")

    # 所有的测试用例都运行完毕才会关闭浏览器
    def teardown_class(self):
        sleep(2)
        self.driver.quit()

    def test_01_login_suc(self):
        # a。使用Xpath 文本定位策略定位登录超链接,并点击
        self.driver.find_element_by_xpath("//*[text()='登录']").click()
        # b。使用Xpath 属性定位策略定位用户名输入框,并输入13600001111
        self.driver.find_element_by_xpath("//*[@id='username']").send_keys("13600001111")
        # c。使用Xpath  属性包含定位策略定位密码输入框,并输入123456
        self.driver.find_element_by_xpath("//*[contains(@id,'pass')]").send_keys("123456")
        # d。使用Xpath  属性与逻辑结合策略定位验证码输入框,并输入8888
        self.driver.find_element_by_xpath('//*[@placeholder="验证码" and @id="verify_code"]').send_keys("8888")
        # e。使用Xpath 层级与属性结合策略定位登录按钮,并点击;
        self.driver.find_element_by_xpath("//*[@class='login_bnt']/a").click()
        sleep(2)

    def test_02_add_address(self):
        # 2、在个人中心页面点击【账户设置】下【收货地址】
        ActionChains(self.driver).move_to_element(self.driver.find_element(By.XPATH, "//*[text()='账户设置']")).perform()
        self.driver.find_element(By.XPATH, "//*[text()='收货地址']").click()
        """
        # (*)获取当前已经保存地址条数
        old_num = self.driver.find_elements(By.CSS_SELECTOR, "em.red")[0].text
        print(f"新增地址前,已保存的地址条数为{old_num}")
        """

        # 3、点击【新增地址】:收货人信息 = cus{当前时间}
        self.driver.find_element(By.XPATH, "//*[text()='增加新地址']").click()

        customer_name = f"cus{time.strftime('%H_%M_%S')}"
        # 4、完成新增地址操作
        self.driver.find_element(By.CSS_SELECTOR, '[name="consignee"]').send_keys(customer_name)
        self.driver.find_element(By.CSS_SELECTOR, '[name="mobile"]').send_keys("13600001112")

        Select(self.driver.find_element(By.ID, "province")).select_by_value("1")  # value属性值为1,代表北京
        Select(self.driver.find_element(By.ID, "city")).select_by_value("2")     # 市辖区2
        Select(self.driver.find_element(By.ID, "district")).select_by_value("39")  # 朝阳区39
        Select(self.driver.find_element(By.ID, "twon")).select_by_value("40")  # 建外街道40

        self.driver.find_element(By.CSS_SELECTOR, '[name="address"]').send_keys("幸福门街道26栋")
        self.driver.find_element(By.CSS_SELECTOR, '[name="zipcode"]').send_keys("100000")

        self.driver.find_element(By.ID, "address_submit").click()
        # 当UI自动化脚本操作功能时,如该步骤会自动触发发送请求,最好在触发之后跟上强制等待1秒,防止发送请求失败
        sleep(1)

        """
        # 5、控制滚动条移动到页面最底部
        js_str = "window.scrollTo(0,2000)"
        self.driver.execute_script(js_str)
        sleep(2)
        # 6、刷新下界面
        self.driver.refresh()
        # (*)再次获取当前已经保存地址条数
        new_num = self.driver.find_elements(By.CSS_SELECTOR, "em.red")[0].text
        print(f"新增地址前,已保存的地址条数为{new_num}")
        # (*)判断新增完后的地址条数是否+1 如果+1则打印新增成功,否则打印新增失败
        if int(new_num) -1 == int(old_num):
            print("新增成功")
        else:
            print("新增失败")
        """
        # 根据本次新增的【收货人】信息的文本,到界面上找元素,如果能找到则代表信息成功,找不到则失败截图

        try:
            # 显示等待
            # 如果找到元素对象则把元素对象赋值给is_suc变量
            is_suc = WebDriverWait(self.driver, 10,1).until(lambda x:x.find_element(By.XPATH, f"//*[text()='{customer_name}']"))
        except Exception as e:
            # 找不到则给is_suc变量赋值为False
            is_suc = False
            # 截图
            self.driver.get_screenshot_as_file("新增地址失败.png")
        assert is_suc

三、pycharm中测试框架选择

File------>Settings------>Tools------>Python Integrated Tools------>Testing: Default test runner------>下拉框选择测试框架

相关推荐
腾科IT教育15 小时前
HarmonyOS开发|ArkTS UI颜色API通用规则
ui·华为·harmonyos·harmonyos开发·鸿蒙应用开发工程师
小小工匠1 天前
把生成模型接进 Agent:Higgsfield MCP 的架构拆解与工程实践
ui·higgsfield mcp·impeccable
AmyLin_20011 天前
AI 如何做出数学发现【5】- AI 数学证明怎样做单元测试:从“看起来顺”到可否证工作流
人工智能·单元测试·openai·数学推理·符号计算·ai推理·反例生成
czhaii1 天前
word插入表格排版创建或编辑应用技巧
ui·c#·xhtml
是小艺吗。1 天前
第三方机构出具的软件功能测试报告的作用与流程说明,中承信安专业讲解
功能测试·单元测试·软件测试报告·软件功能测试·软件测评
淼澄研学2 天前
OpenAI集成Photoshop API:函数调用机制解析与实操指南
ui·photoshop
学习使我健康2 天前
一个基于 **Jetpack Compose + Material 3** 的 Android 入门示例项目,演示 Compose 声明式 UI 的核心用法
ui·kotlin·android jetpack
一夜白头催人泪2 天前
从0到1搭建AI驱动的UI自动化:无代码DOM设计文档
人工智能·ui·自动化
测试老哥2 天前
软件测试:单元测试详解
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
星辰即远方2 天前
计算器仿写总结
学习·ui·ios·cocoa·xcode