当前位置: 首页 > news >正文

软件测试进阶篇----自动化测试脚本开发

自动化测试脚本开发

一、自动化测试用例开发

1、用例设计需要注意的点

image-20230921152728082

2、设计一条测试用例

image-20230921152749418

二、脚本开发过程中的技术

1、线性脚本开发

2、模块化脚本开发(封装线性代码到方法或者类中。在需要的地方进行调用)

3、关键字驱动开发:selenium ide关键字驱动开发

4、数据驱动开发:数据和脚本分离。数据专门存储在外部的文件中。(结合unittest框架的ddt(data driver test)模块)

5、po设计模式:将页面中的元素和操作的方法封装在一个页面对象中,只需要调用对象中封装的元素和操作方法来实现测试用例,不需要真实的页面

三、蜜蜂电商系统的脚本设计-1

采用python+selenium+unitte实现自动化测试的基本脚本,还会涉及到ddt+json实现数据驱动,git和gitee实现持续集成。

1、前期准备

  • public:放公共访问、公用的一些模块:发邮件的模块、记录日志的模块、登录模块、登出模块等
  • testcases:放所有采用unittest框架设计的测试用例的模块
    • register
      • mifeng_register.py
      • mifeng_register_username.py
      • mifeng_register_email.py
      • ……
    • login
      • mifeng_login.py
      • mifeng_login_username.py
      • ……
    • search
    • gouwu
    • order
    • pay
  • testdata:测试用例所需要的数据驱动文件,采用json文件
    • mifeng_register.json
    • …….
  • testreport:html格式的测试报告文件
    • 09211412.html
  • testlog:日志文件
  • maintest.py:入口文件、主运行文件

2、正向注册用例设计


# 采用unittest框架,实现正向注册的用例
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
import time# 单元测试用例
class mifeng_register(unittest.TestCase):def setUp(self):# 创建浏览器对象self.driver = webdriver.Chrome()self.driver.maximize_window()self.driver.implicitly_wait(10)# 打开某电商首页self.driver.get('xxx')def test_register(self):'''正向注册功能测试用例'''# # 打开蜜蜂电商首页# self.driver.get('')# 点击首页的“免费注册”按钮timestr = time.strftime("%H%M%S")username = "blue_" + timestremail = username + "@163.com"self.driver.find_element(By.LINK_TEXT, '免费注册').click()# 输入正向的用户名self.driver.find_element(By.ID, 'username').send_keys(username)# 输入正向的邮箱self.driver.find_element(By.ID, 'email').send_keys(email)# 输入正向的密码self.driver.find_element(By.ID, 'password').send_keys('123456')# 输入正向的确认密码self.driver.find_element(By.ID, 'repassword').send_keys('123456')# 勾选协议# 点击“立即注册”按钮self.driver.find_element(By.LINK_TEXT, '立即注册').click()# 强制等待,先等5s,跳过中间页面time.sleep(5)# 断言sj = self.driver.find_element(By.XPATH, '/html/body/div[4]/div[1]/div[2]/div[1]/div[1]/h3/font[1]').textyq = usernameself.assertEqual(yq, sj, '预期结果和实际结果不一致')def test_register_chongfu(self):'''重复注册功能测试用例'''# 打开电商首页self.driver.get('xxx')# 点击首页的“免费注册”按钮self.driver.find_element(By.LINK_TEXT, '免费注册').click()# 输入正向的用户名self.driver.find_element(By.ID, 'username').send_keys('blue_002')# 输入正向的邮箱self.driver.find_element(By.ID, 'email').send_keys('blue_002@163.com')# 输入正向的密码self.driver.find_element(By.ID, 'password').send_keys('123456')# 输入正向的确认密码self.driver.find_element(By.ID, 'repassword').send_keys('123456')# 勾选协议# 点击“立即注册”按钮self.driver.find_element(By.LINK_TEXT, '立即注册').click()# 强制等待,先等5s,跳过中间页面time.sleep(5)# 断言# sj = self.driver.find_element(By.XPATH,'/html/body/div[4]/div[1]/div[2]/div[1]/div[1]/h3/font[1]').textsj = self.driver.current_urlyq = r'xxx'# yq='blue_002'self.assertEqual(yq, sj, '预期结果和实际结果不一致')def tearDown(self):# 关闭浏览器self.driver.quit()if __name__ == '__main__':unittest.main()

3、主运行文件

# 主运行文件:获取测试用例集合、运行测试用例集合、得到可视化测试报告....
import unittest
from BeautifulReport import BeautifulReport
import time# 获取测试集合
# 获取级联(指定父目录,可以遍历子目录,要求目录必须是包)目录下的测试用例
discover = unittest.defaultTestLoader.discover(r'./TestCases/',pattern='mifeng*.py')
print(discover)# 用时间戳作为测试报告的文件名
strTime = time.strftime('%m%d%H%M')
filename = 'report_'+strTime# 创建运行器对象
runner = BeautifulReport(discover)
runner.report('电商自动化测试报告',filename,'./TestReport/')

4、登录模块的测试用例

# 采用unittest框架,实现正向登录的用例
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
import time# 单元测试用例
class mifeng_login(unittest.TestCase):def setUp(self):# 创建浏览器对象self.driver = webdriver.Chrome()self.driver.maximize_window()self.driver.implicitly_wait(10)# 打开电商首页self.driver.get('xxx')def test_login_01(self):'''正常登录的测试用例'''# self.driver.get('xxx')self.driver.find_element(By.LINK_TEXT, '登陆').click()# 输入用户名和密码(正向数据)self.driver.find_element(By.ID, 'username').send_keys('blue_001')self.driver.find_element(By.ID, 'password').send_keys('123456')# 点击登陆按钮self.driver.find_element(By.XPATH, '//*[@id="login-form"]/div/a').click()# 断言time.sleep(5)sj = self.driver.find_element(By.XPATH, '/html/body/div[4]/div[1]/div[2]/div[1]/div[1]/h3/font[1]').textyq = 'blue_001'self.assertEqual(yq, sj, '预期结果和实际结果不一致!!!')def test_login_02(self):'''登录用户名为空的测试用例'''# self.driver.get('xxx')self.driver.find_element(By.LINK_TEXT, '登陆').click()# 用户名设置为空self.driver.find_element(By.ID, 'username').send_keys('')self.driver.find_element(By.ID, 'password').send_keys('123456')# 点击登陆按钮self.driver.find_element(By.XPATH, '//*[@id="login-form"]/div/a').click()# 断言time.sleep(5)sj = self.driver.find_element(By.XPATH, '//*[@id="login-form"]/div/dl[1]/dd/span/font').textyq = '请输入用户名'self.assertEqual(yq, sj, '预期结果和实际结果不一致!!!')def test_login_03(self):'''未注册用户名登录的测试用例'''# self.driver.get('xxx')self.driver.find_element(By.LINK_TEXT, '登陆').click()# 用户名设置为空self.driver.find_element(By.ID, 'username').send_keys('blue01')self.driver.find_element(By.ID, 'password').send_keys('123456')# 点击登陆按钮self.driver.find_element(By.XPATH, '//*[@id="login-form"]/div/a').click()# 断言time.sleep(5)sj = self.driver.current_urlyq = 'xxx'self.assertEqual(yq, sj, '预期结果和实际结果不一致!!!')def tearDown(self):self.driver.quit()if __name__ == '__main__':unittest.main()

5、级联目录下的用例获取

# 主运行文件:获取测试用例集合、运行测试用例集合、得到可视化测试报告....
import unittest
from BeautifulReport import BeautifulReport
import time# 获取测试集合
# 获取级联(指定父目录,可以遍历子目录,要求目录必须是包)目录下的测试用例
discover = unittest.defaultTestLoader.discover(r'./TestCases/',pattern='mifeng*.py')
print(discover)

6、修改个人资料的测试用例

# 采用unittest框架,实现一个个人资料正常更新的用例
# 先登录--更新资料--退出
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from 电商项目1.Public.Basic import login,logout# 单元测试用例
class mifeng_userinfo(unittest.TestCase):def setUp(self):# 创建浏览器对象self.driver = webdriver.Chrome()self.driver.maximize_window()self.driver.implicitly_wait(10)# 先登录login(self.driver)def test_userinfo_01(self):'''正向个人资料修改功能测试用例'''# 登录成功,改资料# 点击个人资料超链接self.driver.find_element(By.LINK_TEXT,'个人资料').click()time.sleep(2)# 设置昵称、QQ和性别、出生日期等self.driver.find_element(By.ID, 'nickname').clear()self.driver.find_element(By.ID,'nickname').send_keys('王同学')self.driver.find_element(By.ID, 'qq').clear()self.driver.find_element(By.ID,'qq').send_keys('2659160211')self.driver.find_element(By.XPATH,'//*[@id="profile-form"]/dl[3]/dd/label[2]/input').click()self.driver.find_element(By.XPATH,'//*[@id="birth_year"]/option[78]').click()self.driver.find_element(By.XPATH,'//*[@id="birth_month"]/option[2]').click()self.driver.find_element(By.XPATH,'//*[@id="birth_day"]/option[20]').click()# 点击更新按钮self.driver.find_element(By.CSS_SELECTOR,'#profile-form > div > button').click()# 断言sj = self.driver.find_element(By.XPATH,'/html/body/div/div[2]/h3').textyq = '更新资料成功'self.assertEqual(yq,sj)def test_userinfo_02(self):'''更新个人资料头像修改功能测试用例'''# 登录成功,改资料# 点击个人资料超键self.driver.find_element(By.LINK_TEXT,'个人资料').click()time.sleep(2)# 提交头像self.driver.find_element(By.NAME,'avatar_file').send_keys(r'd:/aa.jpg')# 保存头像self.driver.find_element(By.ID,'save-avatar-btn').click()# 点击更新按钮self.driver.find_element(By.CSS_SELECTOR,'#profile-form > div > button').click()# 断言sj = self.driver.find_element(By.XPATH,'/html/body/div/div[2]/h3').textyq = '更新资料成功'self.assertEqual(yq,sj)def tearDown(self):# 退出logout(self.driver)# 关闭浏览器self.driver.quit()if __name__=='__main__':unittest.main()

8、数据驱动测试

对设计过的用例使用数据驱动的方式实现

数据驱动:由于数据的变化,而导致结果的不同(来实现不同的测试用例)的过程。

实现数据驱动:数据和脚本步骤分离式管理

数据的存储方式:

  • json
  • csv
  • excel
  • yaml
  • 数据库–pymysql

知识点:python+unittest+ddt+json来实现数据驱动

使用ddt实现数据驱动的步骤:

  • 安装ddt模块:pip install ddt
  • 准备一个json数据文件:
  • 在用例模块中导入ddt的两个类:file_data、ddt
  • @ddt修饰类
  • @file_data(json文件)修饰单元测试用例方法:
  • 单元测试用例方法的参数要和数据文件中保持一致
  • 使用用例的参数替换掉对应的脚本中的常量值

9、邮件发送

10、日志记录

把测试用例执行情况记录在一个文件中,便于后续的查验。

步骤:

  • 编写logging的配置文件
  • 在主运行文件中调用一次配置文件(和配置文件如何设计有关)
    • 如果配置文件是线性代码,直接导入一次即可
    • 如果配置文件封装在方法中,导入方法并调用一次
    • 如果封装在类中的方法里,导入类、创建对象调方法
  • 测试用例中,导入logging模块
  • logging调用不同等级的日志输出方法
    • fatal()
    • error()
    • info()
    • debug()

四、代码的版本管理

版本管理:多人协作、自动化脚本开发的时候,需要进行版本的维护

  1. 版本管理介绍

    • svn:集中式的版本管理工具
    • 分布式版本管理
      • git:版本管理工具
      • gitee:码云,远程仓库
      • github、gitlib:这几个都是主流的仓库
  2. gitee注册

  3. git的版本管理的常见命令

    1. 常见的工作区间

      • workspace:工作区,可以理解为你自己开发代码的文件夹,包含一个.git隐藏文件夹(git init)

      • staging area:暂存区/缓存区(临时存储文件的地方)

      • local repository:本地仓库

      • remote repository:远程仓库

    2. 常见的命令

      • add:将工作区的文件添加到缓存区
      • commit:将缓存区的数据提交到本地仓库
      • git push:将本地仓库的文件上传到远程仓库
      • clone:从远程仓库到本地仓库,一般第一次从远程下载,建议使用
      • pull:从远程仓库到本地工作区,一般已经在本地有了文件版本的情况下使用
    3. 配置SSH公钥

    4. 在gitee上创建一个空的仓库

    5. Git 全局设置:

      git config --global user.name "王同学"
      git config --global user.email "w123456@163.com"
      
    6. 从本地上传脚本到远程仓库

      先创建本地工作空间

      添加工作空间下的文件到缓存区:

      • git add *:将当前工作区的所有文件都加到缓存区
      • git add a.txt:只加这一个文件

      缓存区数据保存到本地仓库:git commit -m “v1”

      本地仓库和远程仓库建立关联:git remote add origin gitee仓库项目地址

      本地仓库上传到远程仓库:git push -u origin “master”

      回到gitee,刷新仓库

    mkdir blue-mi-feng
    cd blue-mi-feng
    git init 
    touch README.md
    git add README.md
    git commit -m "first commit"
    git remote add origin gitee仓库项目地址
    git push -u origin "master"
    

    从远程下载到本地:git clone 地址


已经可以将自动化代码上传到gitee远程仓库进行管理了。

后续就可以直接从远程仓库,借助jenkins工具实现自动部署和运行(定时运行,触发运行)

五、jenkins实现持续集成

1、jenkins软件的安装

  • 需要jdk11的支持,所以提前安装jdk11(java的语言包)
  • 安装jenkins对应的支持jdk11的版本
  • jenkins软件+插件安装两部分(有一部分安装失败不影响使用)
  • 记住用户名和密码

2、jenkins的环境变量配置

作用和windows系统的环境变量配置很相似

jenkins+git实现自动化部署和执行,需要安装git和gitee插件,作相应的配置即可

3、插件安装和配置

1、需要安装git和gitee插件

2、配置git全局的环境配置

3、gitee中获取私人令牌

4、在jenkins中配置gitee参数

5、添加用户名和密码凭据

4、创建jenkins任务

1、新建项目

2、配置git仓库

3、触发任务设置

4、添加window批处理构建

保存退出

5、运行任务

等待设置的定时时间


六、pom设计模式

1、pom概述

==POM(Page Object Model)==是一种自动化测试设计模式,它将页面对象和测试用例代码分离开来,使测试代码更加清晰和易于维护

POM模式的核心思想是将每个页面视为一个对象(类),并将页面的元素和操作封装在该对象中。测试代码只需要调用页面对象的方法,而不需要关心页面的具体实现细节。

POM模式的优点包括:

  1. 提高测试代码的可读性和可维护性:测试代码只需要调用页面对象的方法,而不需要关心页面的具体实现细节,使测试代码更加清晰和易于维护。
  2. 提高测试代码的复用性:页面对象可以在多个测试用例中重复使用,减少了代码的重复编写
  3. 操作提高测试代码的稳定性:页面对象的封装可以避免测试代码对页面元素的直接操作,减少了测试代码对页面的依赖,从而提高了测试代码的稳定性

POM模式的实现步骤包括:

  1. 封装页面元素定位和操作方法:将页面元素和操作封装在页面对象中,可以使用selenium或其他自动化测试工具提供的API
  2. 创建页面对象:将每个页面视为一个对象,并将页面的元素和操作封装在该对象中进行调用
  3. 编写测试代码:测试代码只需要调用页面对象的方法,而不需要关心页面的具体实现细节
  4. 执行测试用例:执行测试用例时,测试代码会调用页面对象的方法,完成测试操作

总之,POM模式是一种优秀的自动化测试设计模式,可以提高测试代码的可读性、可维护性、复用性和稳定性。在实际的自动化测试中,可以根据具体的需求和场景选择是否采用POM模式

image-20230926142405159

2、做项目目录分层

  • common
    • commondriver.py:封装webdriver api常见的方法
    • 邮件、日志的模块放在该目录下
  • pageobject
    • RegisterPO
    • LoginPO
    • xxxPO
  • testcases
    • login
      • mifeng_login.py
      • mifeng_login_username.py
      • xxx
    • register
      • mifeng_register.py
      • mifeng_register_username.py
      • xxx
    • xxx
  • testreport
  • testlog
  • maintest.py

3、commondriver设计

# 实现封装webdriver api方法的,创建浏览器对象、页面打开、页面元素定位、点击、输入、获取文本、切换窗口、弹框、frame等
# 对开源软件webdriver的二次封装
from selenium import webdriver
from selenium.webdriver.common.by import By
import timeclass commondriver():'''功能:构造方法,实现的是变量的初始化'''def __init__(self):# 可以先将self.driver变量看作是Chrome浏览器的对象# 声明调用的对象,固定写法self.driver: webdriver.Chrome = None# 实现一个打开浏览器的方法,设计一个方法:给不同的参数,可以启动不同的浏览器对象def open_browser(self, browser="chrome"):'''功能:实现一个打开浏览器的方法:param browser: 可以是chrome、ff、firefox、safari、edge等:return:暂时先不给,后面可以给self.driver'''if (browser == 'ff' or browser == 'firefox'):self.driver = webdriver.Firefox()elif (browser == 'edge'):self.driver = webdriver.Edge()else:self.driver = webdriver.Chrome()# 实现浏览器的最大化显示,页面元素的隐式等待self.driver.maximize_window()self.driver.implicitly_wait(10)# 在多页面操作的时候,需要使用同一个页面对象return self.driver# 关闭浏览器对象def close_browser(self):'''功能:关闭浏览器对象:return:'''self.driver.quit()# 打开指定的url地址页面,是需要参数urldef open_url(self, url=''):'''功能:打开指定的url地址:param url: 页面地址:return: 不需要'''if (url.startswith('http') or url.startswith('https')):self.driver.get(url)else:print('输入的地址不正确,请重新输入!')# 页面元素定位和操作:self.driver.find_element(By.ZZ,'xx').yy()# 定义页面定位方法为私有的,只在本类内调用,其他不能调用def __find_element(self, locator=''):'''功能:通过给定的定位器,来判断是哪一种定位方式(xpath\css\id\linktext):param locator: 是属性值:return:element元素对象'''if (locator.startswith('/') or locator.startswith('//')):# 符合上面条件的定位方式是xpath定位element = self.driver.find_element(By.XPATH, locator)elif (locator.startswith('.') or (locator.startswith('#') or locator.startswith('['))):# 符合上面条件的定位方式是css定位element = self.driver.find_element(By.CSS_SELECTOR, locator)else:# 默认是idtry:element = self.driver.find_element(By.ID, locator)except:element = self.driver.find_element(By.LINK_TEXT, locator)# 返回element页面元素对象return element# 封装文本框的输入方法(具备提前清空功能)# 两个参数:定位器locator、输入的数据valuedef input(self, locator='', value=''):'''功能:定位文本框,清空内容,输入文本:param locator: 定位器:param value: 输入的值:return: 不需要'''element = self.__find_element(locator)element.clear()element.send_keys(value)# 定义一个click点击方法def click(self, locator=''):'''功能:定位元素并点击:param locator::return:'''element = self.__find_element(locator)element.click()# 获取页面元素的文本信息def get_text(self, locator=''):'''功能:获取页面元素的文本信息:param locator::return: 返回获取的文本'''element = self.__find_element(locator)return element.text# switch_to的用法def switch_to(self, type='window', locator=''):'''功能:切换窗口和frame:param type::param locator::return:'''if (type == 'frame'):element = self.__find_element(locator)self.driver.switch_to.frame(element)else:handles = self.driver.window_handlesself.driver.switch_to.window(handles[-1])# 待补充后续需要的方法即可def get_current_url(self):'''获取页面的地址:return:'''return self.driver.current_urlif __name__ == '__main__':# 创建该类的对象cd = commondriver()cd.open_browser('')# 打开百度页面cd.open_url('https://www.baidu.com')time.sleep(2)# 定位百度文本框并输入CSDN叫我王同学cd.input('kw', 'CSDN叫我王同学')time.sleep(2)# 点击百度一下按钮cd.click('su')time.sleep(2)# 关闭浏览器cd.close_browser()

4、注册页面对象设计

# http://shop.mifeng.qfedu.com/
# 电商注册页面的一些特点:url、用户名、邮箱文本、密码、确认密码文本框、勾选复选框、立即注册按钮、登陆按钮、异常提示信息框
import time
from MiFengShopPO.common.commondriver import commondriver# 封装注册页面类,使页面直接继承使用封装好的通用api方法
class RegisterPage(commondriver):# 构造方法:只需要指定注册页面的url地址即可def __init__(self,driver):'''功能:初始化注册页面的地址,直接绑定在类中'''# 接收外部一个统一的页面对象到当前页面self.driver = driverself.url = 'xxx'# 封装注册页面上的用户名文本框:输入值def input_username(self, value=''):'''功能:定位用户名文本框(直接指定使用id属性定位),并且绑定其输入功能:param value: 输入的数据:return:'''self.input('username', value)def input_email(self, value=''):'''功能:定位邮箱文本框,并且绑定其输入功能:param value: 输入的数据:return:'''self.input('email', value)def input_password(self, value=''):'''功能:定位密码文本框(直接指定使用id属性定位),并且绑定其输入功能:param value: 输入的数据:return:'''self.input('password', value)def input_repassword(self, value=''):'''功能:定位确认密码文本框(直接指定使用id属性定位),并且绑定其输入功能:param value: 输入的数据:return:'''self.input('repassword', value)def click_agree(self):'''功能:定位同意协议(id属性)并点击:return:'''self.click('agree')def click_registerNow(self):'''功能:定位立即注册(XPATH)并点击:return:'''self.click('//*[@id="register-form"]/div/div[2]/a')def click_login(self):'''功能:定位登陆按钮(XPATH)并点击,LINK_TEXT效率低:return:'''self.click('/html/body/div[2]/div/div/div/div/a')def get_username_text(self):'''功能:获取用户名对应的错误提示信息:return:返回值是错误信息'''text = self.get_text('#register-form > div > dl:nth-child(1) > dd > span > font')return textdef get_email_text(self):'''功能:获取邮箱对应的错误提示信息:return:返回值是错误信息'''text = self.get_text('#register-form > div > dl:nth-child(2) > dd > span > font')return textdef get_password_text(self):'''功能:获取密码对应的错误提示信息:return:返回值是错误信息'''text = self.get_text('//*[@id="register-form"]/div/dl[3]/dd/span/font')return textdef get_repassword_text(self):'''功能:获取确认密码对应的错误提示信息:return:返回值是错误信息'''text = self.get_text('//*[@id="register-form"]/div/dl[4]/dd/span/font')return textif __name__ == '__main__':# 先创建页面rp = RegisterPage()rp.open_browser()rp.open_url(rp.url)# 输入用户名为空rp.input_username('')# 输入邮箱rp.input_email('blue_001@163.com')# 输入密码rp.input_password('123456')# 输入确认密码rp.input_repassword('123456')# 点击立即注册按钮rp.click_registerNow()time.sleep(1)# 断言yq = '请设置用户名'sj = rp.get_username_text()assert yq == sj

5、测试用例层设计

import time
# 反向的注册的用例,结合unittest框架
import unittest
from MiFengShopPO.pageobject.RegisterPage import RegisterPage# 创建单元测试类
class mifeng_register_username(unittest.TestCase):def setUp(self):# 创建注册页面对象self.rp = RegisterPage()# 打开Chrome浏览器self.rp.open_browser()# 打开电商注册页面self.rp.open_url(self.rp.url)def test_register_username_01(self):'''用户名为空:return:'''self.rp.input_username('')self.rp.input_email('blue_012@163.com')self.rp.input_password('123456')self.rp.input_repassword('123456')self.rp.click_registerNow()# 断言time.sleep(5)yq = '请设置用户名'sj = self.rp.get_username_text()self.assertEqual(yq,sj)def test_register_username_02(self):'''用户名为test:return:'''self.rp.input_username('test')self.rp.input_email('blue_013@163.com')self.rp.input_password('123456')self.rp.input_repassword('123456')self.rp.click_registerNow()# 断言time.sleep(5)yq = '用户名不符合格式要求'sj = self.rp.get_username_text()self.assertEqual(yq,sj)def test_register_username_03(self):'''用户名为数字开头:return:'''self.rp.input_username('123test')self.rp.input_email('blue_014@163.com')self.rp.input_password('123456')self.rp.input_repassword('123456')self.rp.click_registerNow()# 断言time.sleep(5)yq = '用户名不符合格式要求'sj = self.rp.get_username_text()self.assertEqual(yq,sj)def test_register_username_04(self):'''用户名含特殊符号:return:'''self.rp.input_username('ad#¥#¥#¥')self.rp.input_email('blue_015@163.com')self.rp.input_password('123456')self.rp.input_repassword('123456')self.rp.click_registerNow()# 断言time.sleep(5)yq = '用户名不符合格式要求'sj = self.rp.get_username_text()self.assertEqual(yq,sj)def tearDown(self):# 关闭浏览器self.rp.close_browser()if __name__ =='__main__':unittest.main()

6、maintest主运行文件

import unittest
from selenium import webdriver
import time
from BeautifulReport import BeautifulReportdiscover = unittest.defaultTestLoader.discover('./testcases/register',pattern='mifeng_*.py')filename = 'report_'+time.strftime('%m%d%H%M')
runner = BeautifulReport(discover)
runner.report('报告',filename,'./testreport/')

7、多页面交互设计

登录用例的实现:涉及到登录页面和中间跳转页面

import unittest
from MiFengShopPO.common.commondriver import commondriver
from MiFengShopPO.pageobject.LoginPage import LoginPage
from MiFengShopPO.pageobject.TiaoZhuanPage import TiaoZhuanPageclass mifeng_login(unittest.TestCase):def setUp(self):# 创建一个统一的浏览器对象self.driver = commondriver().open_browser()# 创建登录的对象,打开登录页面self.lp = LoginPage(self.driver)self.lp.open_url(self.lp.url)def test_login_01(self):'''正向测试用例:return:'''self.lp.input_username('blue_001')self.lp.input_password('123456')self.lp.click_login()# 断言:采用跳转页面的元素做断言self.tzp = TiaoZhuanPage(self.driver)sj = self.tzp.get_tiaozhuan_text()yq = '登录成功'self.assertEqual(yq,sj)def tearDown(self):self.lp.close_browser()if __name__=='__main__':unittest.main()
import unittest
from MiFengShopPO.common.commondriver import commondriver
from MiFengShopPO.pageobject.LoginPage import LoginPage
from MiFengShopPO.pageobject.TiaoZhuanPage import TiaoZhuanPageclass mifeng_login(unittest.TestCase):def setUp(self):# 创建一个统一的浏览器对象self.driver = commondriver().open_browser()# 创建登录的对象,打开登录页面self.lp = LoginPage(self.driver)self.lp.open_url(self.lp.url)def test_login_01(self):'''正向测试用例:return:'''self.lp.input_username('blue_001')self.lp.input_password('123456')self.lp.click_login()# 断言:采用跳转页面的元素做断言self.tzp = TiaoZhuanPage(self.driver)sj = self.tzp.get_tiaozhuan_text()yq = '登录成功'self.assertEqual(yq,sj)def tearDown(self):self.lp.close_browser()if __name__=='__main__':unittest.main()```

相关文章:

软件测试进阶篇----自动化测试脚本开发

自动化测试脚本开发 一、自动化测试用例开发 1、用例设计需要注意的点 2、设计一条测试用例 二、脚本开发过程中的技术 1、线性脚本开发 2、模块化脚本开发(封装线性代码到方法或者类中。在需要的地方进行调用) 3、关键字驱动开发:selen…...

rust std

目录 一,std基本数据结构 1,std::option 2,std::result 二,std容器 1,vector 三,std算法 1,排序 2,二分 (1)vector二分 (2)…...

SpringMVC(下)

1、拦截器&#xff1a; 1、拦截器的配置: SpringMVC中的拦截器用于拦截控制器方法的执行 SpringMVC中的拦截器需要实现HandlerInterceptor <!--配置拦截器--><mvc:interceptors><!--对所有的请求进行拦截--><!--<bean class"com.songzhishu.m…...

分布式操作系统的必要性及重要性

总有人在各个平台留言或者私信问LAXCUS分布式操作系统的各种问题&#xff0c;尤其是关于分布式操作系统的应用市场、价值、意义之类的问题。我们团队做LAXCUS分布式操作系统&#xff0c;也不是头脑凭空发热&#xff0c;是基于我们之前的大量产品设计、经验逐渐一步步做起来。当…...

【Javascript】定时器

目录 延迟执行 定时执行 清除定时任务 延迟执行 setTimeout(function(){}, 毫秒) console.log(1); console.log(2); console.log(3); setTimeout(function (){console.log(5) },5000) console.log(4);setTimeout(function (){ console.log(5) },5000) 设定了一个任务&…...

基于stm32的ADC读取烟雾报警器的数值

本文想要设计一个设计一个有stm32控制的烟雾报警系统。通过MQ-2烟雾报警器将获取模拟的数值传递给stm32的ADC外设并在串口助手上显示对应的电压值。烟雾报警器浓度越高&#xff0c;他的电压就越高&#xff0c;但是不会超过3.3V。设置一个电压临界值&#xff0c;当传输回来的电压…...

无需更换vue-cli 脚手架 uniapp-搭建项目-H5-低版本安卓IOS兼容问题(白屏)(接口请求异常)

✨求关注~ &#x1f4bb;博客&#xff1a;www.protaos.com I. 简介 A. UniApp项目概述 B. 白屏和接口请求异常问题的背景 II. 白屏问题 A. 问题描述 1、uniapp 打包H5内嵌入APP内、低版本手机系统访问白屏问题 B. 问题根本原因 1、低版本手机系统 自带的webview内核不支持ES6语…...

【IO面试题 四】、介绍一下Java的序列化与反序列化

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;介绍一下Java的序列化与…...

M1本地部署Stable Diffusion

下载安装 参考博客: 在Mac上部署Stable Diffusion&#xff08;超详细&#xff0c;AI 绘画入门保姆级教程&#xff09; 安装需要的依赖库 brew install cmake protobuf rust python3.10 git wget 可能中途会存在下载报错或者下载卡主的问题,需要切国内源 brew进行替换源: …...

java中的内存分配

目录 1.堆内存 2.栈内存 3.常量池 4.寄存器 5.示例 6.总结 1.堆内存 堆用来存放程序中动态生产的数据&#xff0c;如new出来的对象。 通过new方式创建的对象&#xff0c;数组及字符串都有自己的内存地址。 方法调用完毕后&#xff0c;方法中new出来的对象就会变成垃圾…...

Matter.js 插件:matter-wrap(世界是圆的)

本文简介 点赞 关注 收藏 学会了 记得以前看爆笑校园里有一集讲到&#xff0c;一个人对着前面开了一枪&#xff0c;过了一阵子弹打中他自己的后脑勺。作者想通过这个冷笑话告诉大家一件事&#xff1a;地球是圆的。 在 Matter.js 世界里&#xff0c;默认是没有边界的&#…...

HCIA --- ACL(访问控制列表)

ACL访问控制列表 一、作用 访问控制 --- 在路由器流量进或出的接口上&#xff0c;匹配流量产生动作---允许、拒绝定义感兴趣流量 --- 抓取流量&#xff0c;之后给到其他的策略&#xff0c;让其他策略进行工作&#xff1b; 二、匹配规则 至上而下逐一匹配&#xff0c;上条匹…...

Xcode自定义快捷键

一、新建脚本 1. 编写脚本 把脚本sh文件保存在安全的目录&#xff0c;不会被删除 我这里主要是两个常用的&#xff1a; 1.打开终端: xcode-terminal.sh #!/bin/shif [ -n "$XcodeProjectPath" ]; then open -a Terminal "$XcodeProjectPath"/.. elseo…...

jmeter界面压测过程卡死解决思路

1、排查压测机的资源是否充足&#xff1b; 2、检查jmeter压测脚本&#xff0c;除聚合报告的所有组件关闭&#xff1b; 我在压测过程中出现频繁卡死&#xff0c;就是查看结果数和断言结果信息量过多导致&#xff1a; 3、直接用非gui界面形式&#xff0c;也就是脚本形式压测。...

听GPT 讲Rust源代码--library/std(6)

题图来自 Why you should use Python and Rust together[1] File: rust/library/std/src/sys/unix/thread_parking/netbsd.rs 文件netbsd.rs位于Rust源代码的rust/library/std/src/sys/unix/thread_parking目录下。该文件是Rust标准库中用于Unix操作系统的线程等待和唤醒机制的…...

如何使用gpt提高效率

如何使用gpt提高效率 自动化替代人力工作减少创意工作需求技术依赖风险实际应用领域内容生成自动回答问题自动化编程个性化推荐 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客&#x1f466;&#x1f3fb; 《java 面试题大全》 &#x1f369;惟余辈才疏学浅&…...

配置VUE环境过程中 npm报错的处理方案以及VUE环境搭建过程

背景&#xff1a;VUE已经出来很久了&#xff0c;一直想研究这个东西也很久了。由于各种各样的原因&#xff0c;一直没有能处理。最近终于有时间可以研究了。 奈何报错了 嘤嘤嘤~~ 针对报错情况&#xff0c;其实后来没有找到什么好的方案&#xff0c;几经周折&#xff0c;终于搭…...

springboot 配置文件加载顺序

SpringBoot中配置文件的加载顺序是怎样的? 优先级从高到低&#xff0c;高优先级的配置覆盖低优先级的配置&#xff0c;所有配置会形成互补配置。 1.命令行参数。所有的配置都可以在命令行上进行指定; 2.Java系统属性(System.getProperties0) ; 3.操作系统环境变量 4.jar包外…...

二分查找java

一、题目。 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4…...

深入理解Java中的转义字符

最近在学习《两周自制脚本语言》这本书&#xff0c;在词法分析的一些复杂的正则中用到了大量的转义字符’\&#xff0c;比如正则字符串中包含了这个部分\\\\\"你知道它是匹配什么的么&#xff1f; 反斜杠在字符串和正则表达式中都有特殊作用。今天让我们来深入理解一下Ja…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

【若依】框架项目部署笔记

参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作&#xff1a; 压缩包下载&#xff1a;http://download.redis.io/releases 1. 上传压缩包&#xff0c;并进入压缩包所在目录&#xff0c;解压到目标…...

门静脉高压——表现

一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构&#xff1a;由肠系膜上静脉和脾静脉汇合构成&#xff0c;是肝脏血液供应的主要来源。淤血后果&#xff1a;门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血&#xff0c;引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...

6.9本日总结

一、英语 复习默写list11list18&#xff0c;订正07年第3篇阅读 二、数学 学习线代第一讲&#xff0c;写15讲课后题 三、408 学习计组第二章&#xff0c;写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语&#xff1a;复习l默写sit12list17&#…...

[特殊字符] Spring Boot底层原理深度解析与高级面试题精析

一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配&#xff0c;通过简化传统Spring应用的初始化和配置流程&#xff0c;显著提升开发效率。其底层原理可拆解为以下核心机制&#xff1a; 自动装配&#xff08;Auto-Configuration&#xff09; 核…...

从0开始学习R语言--Day17--Cox回归

Cox回归 在用医疗数据作分析时&#xff0c;最常见的是去预测某类病的患者的死亡率或预测他们的结局。但是我们得到的病人数据&#xff0c;往往会有很多的协变量&#xff0c;即使我们通过计算来减少指标对结果的影响&#xff0c;我们的数据中依然会有很多的协变量&#xff0c;且…...