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

自动化测试脚本开发

一、自动化测试用例开发

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()```

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

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

相关文章

【云原生之kubernetes实战】在k8s环境下部署moredoc文库系统

【云原生之kubernetes实战】在k8s环境下部署moredoc文库系统 一、moredoc介绍1.1 moredoc简介1.2 moredoc技术栈二、本次实践介绍2.1 本次实践简介2.2 本次环境规划三、检查k8s环境3.1 检查工作节点状态3.2 检查系统pod状态四、创建mysql的secret资源4.1 创建部署目录4.2 创建密…

rust学习——智能指针

智能指针 在各个编程语言中,指针的概念几乎都是相同的:指针是一个包含了内存地址的变量,该内存地址引用或者指向了另外的数据。 在 Rust 中,最常见的指针类型是引用,引用通过 & 符号表示。不同于其它语言&#xf…

【可视化Java GUI程序设计教程】第4章 布局设计

4.1 布局管理器概述 右击窗体,单击快捷菜单中的Set Layout 4.1.2 绝对布局(Absolute Layout) 缩小窗口发现超出窗口范围的按钮看不见 Absolute Layout 4.1.2 空值布局(Null Layout) 4.1.3 布局管理器的属性和组件布…

python获取安卓Hierarchy并解析

python获取安卓Hierarchy并解析 借助 uiautomator 命令 dump 当前页面的 ui hierarchy 信息 完整的 uiautomator 命令类似: adb shell uiautomator dump [--compressed] [file]解析需要使用:import xml.etree.ElementTree as ET 完整代码如下&#xff…

STM32-通用定时器

通用定时器 通用定时器由一个可编程预分频器驱动的16位自动重新加载计数器组成。应用:测量输入的脉冲长度信号(输入捕获)、产生输出波形(输出比较和PWM)。 脉冲长度和波形周期可以从几微秒调制到几毫秒,使用…

SQL 运算符

SQL 运算符 运算符是保留字或主要用于 SQL 语句的 WHERE 子句中的字符,用于执行操作,例如:比较和算术运算。 这些运算符用于指定 SQL 语句中的条件,并用作语句中多个条件的连词。 常见运算符有以下几种: 算术运算符比…

STM32:TIM通道输入捕获

本文主要讲解如何使用TIMER通道的输入脉冲捕获功能。基于STM32F7的Timer2 Channel3来进行讲解。 配置时钟 Timer2的时钟频率,对应APB1 Timer。 分频设置为96-1,这样设置定时器每次counter加1,对应的时间为1us(计时精度是1us&…

【windows】自动开机 + 免登陆 + 自动运行bat脚本 + 远程免登陆

一、场景 二、解决方案 三、实战 1. 键盘 Win R 键,在弹出的对话框中输入netplwiz,回车 2. 去掉必须输入用户名和密码的勾选,点击应用 3. 在弹出的对话框中输入用户名和密码 一、场景 主机服务器:windows 10 桌面docker &a…

程序包com.sun.xml.internal.bind.marshaller不存在

程序包com.sun.xml.internal.bind.marshaller不存在 需要引入的依赖 <dependency><groupId>org.jetbrains.kotlin</groupId><artifactId>kotlin-stdlib</artifactId><version>1.3.50</version></dependency><dependency&g…

【蓝桥每日一题]-贪心(保姆级教程 篇1)#拼数 #合并果子 #凌乱yyy

目录 题目&#xff1a; 拼数 思路&#xff1a; 题目&#xff1a; 合并果子 思路&#xff1a; 题目&#xff1a;凌乱yyy 思路&#xff1a; 题目&#xff1a;拼数 思路&#xff1a; 思路很简单。举个例子&#xff1a;对于a321,b32。我们发现ab32132,ba32321&#xff0c;那么…

MySQL数据库脱敏方案

MySQL数据库脱敏是指对数据库中的敏感数据进行脱敏处理&#xff0c;以保护数据隐私和安全。常见的脱敏方法包括替换、扰动、加密、去标识化等。 在MySQL数据库中&#xff0c;可以使用以下方法进行脱敏&#xff1a; 替换&#xff1a;将敏感数据的部分或全部替换为其他字符或字…

架构、框架、模式,极简文字介绍

1、架构、框架、模式是一种从大到小的关系&#xff0c;也是一种组合关系 2、架构一般针对一个行业或一类应用&#xff0c;是技术和应用的完美组合 3、框架比较小&#xff0c;很多表现为中间件&#xff0c;框架一般是从技术角度解决同类问题&#xff0c;从技术的横切面来解决实…

LVS负载均衡集群 (NAT模式)

LVS集群 集群的概念&#xff1a; 为解决某个特定的问题&#xff0c;将多个计算机组合起来形成一个单个系统 集群的水平扩展&#xff1a; 增加设备&#xff0c;并行运行多个服务&#xff0c;通过网路连接和算法来调度服务分配的问题 集群的类型&#xff1a; 负载均衡集群&#…

postgresql14-表的管理(四)

表table 创建表 CREATE TABLE table_name --表名 (column_name data_type column_constraint, --字段名、字段类型、约束字段&#xff08;可选&#xff09;column_name data_type, --表级别约束字段...,table_constraint );CREATE TABLE emp1 --创建表 AS SELECT * FROM empl…

Spring Cloud之服务注册与发现(Eureka)

目录 Eureka 介绍 角色 实现流程 单机构建 注册中心 服务提供者 服务消费者 集群搭建 注册中心 服务提供者 自我保护机制 原理分析 Eureka 介绍 Eureka是spring cloud中的一个负责服务注册与发现的组件&#xff0c;本身是基于REST的服务&#xff0c;同时还提供了…

Redis数据库管理工具Redis Desktop Manager最新中文

Redis Desktop Manager是一款直观且易用的Redis数据库管理工具&#xff0c;支持Windows、macOS和Linux等多平台。它提供了丰富的功能和工具&#xff0c;使用户可以轻松地创建、编辑、删除和浏览Redis键值对&#xff0c;并执行各种Redis命令。通过SSH Tunnel连接&#xff0c;RDM…

pip 指定源

pip定源 # 指定豆瓣 python -m pip install transformers -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com参考 出现错误&#xff1a;Looking in indexes:https://pypi.tuna.tsinghua.edu.cn/simple

艾泊宇产品战略:华为手机品牌是如何从低端到高端的

华为在过去一直以几百块钱的低端手机为主&#xff0c;但如今已经可以跟苹果一争高下。 这个转变是华为经过了近二十年的艰苦努力才实现的。 我艾泊宇作为一个亲历者深度研究了华为的成长历程&#xff0c;发现这是一个经典的商业教科书案例。 这里面有很多值得今天中国企业学…

28. 使用 k8e 玩转 kube-vip with Cilium‘s Egress Gateway 特性

因为在私有云环境下,我们需要保障集群服务 APIServer地址的高可用,所以提供的方案就是使用一个 VIP 让 API Server 的流量可以负载均衡的流入集群。另外,kube-vip 还支持 Service LB,方便SVC 服务的负载均衡,结合 cilium Egress Gateway 特性可以做到集群内的容器对外访问…

排序-表排序

当我们需要对一个很大的结构体进行排序时&#xff0c;因为正常的排序需要大量的交换&#xff0c;这就会造成时间复杂度的浪费 因此&#xff0c;我们引入指针&#xff0c;通过指针临时变量的方式来避免时间复杂度的浪费 间接排序-排序思路&#xff1a;通过开辟一个指针数组&…