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

news2024/11/18 15:53:27

自动化测试脚本开发

一、自动化测试用例开发

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_" + timestr
        email = 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]').text
        yq = username
        self.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]').text
        sj = self.driver.current_url
        yq = 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]').text
        yq = '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').text
        yq = '请输入用户名'
        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_url
        yq = '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').text
        yq = '更新资料成功'
        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').text
        yq = '更新资料成功'
        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 time


class 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地址页面,是需要参数url
    def 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:
            # 默认是id
            try:
                element = self.driver.find_element(By.ID, locator)
            except:
                element = self.driver.find_element(By.LINK_TEXT, locator)

        # 返回element页面元素对象
        return element

    # 封装文本框的输入方法(具备提前清空功能)
    # 两个参数:定位器locator、输入的数据value
    def 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_handles
            self.driver.switch_to.window(handles[-1])

    # 待补充后续需要的方法即可
    def get_current_url(self):
        '''
        获取页面的地址
        :return:
        '''
        return self.driver.current_url


if __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 = driver
        self.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 text

    def get_email_text(self):
        '''
        功能:获取邮箱对应的错误提示信息
        :return:返回值是错误信息
        '''
        text = self.get_text('#register-form > div > dl:nth-child(2) > dd > span > font')
        return text

    def get_password_text(self):
        '''
        功能:获取密码对应的错误提示信息
        :return:返回值是错误信息
        '''
        text = self.get_text('//*[@id="register-form"]/div/dl[3]/dd/span/font')
        return text

    def get_repassword_text(self):
        '''
        功能:获取确认密码对应的错误提示信息
        :return:返回值是错误信息
        '''
        text = self.get_text('//*[@id="register-form"]/div/dl[4]/dd/span/font')
        return text


if __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 BeautifulReport

discover = 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 TiaoZhuanPage

class 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 TiaoZhuanPage

class 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.coloradmin.cn/o/1129329.html

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

相关文章

php 数组基础/练习

数组 练习在最后 数组概述 概述与定义 数组中存储键值对 数组实际上是一个有序映射 key-value,可将其当成真正的数组、列表(向量)、散列表、字典、集合、栈、队列等 数组中的元素可以是任意类型的数据对象(可以嵌套数组&#…

AI作画使用指南

AI作画API使用文档请前往:https://blog.csdn.net/qq_48896417/article/details/132520804 一、定义 AI作画使用指南 二、形式 「公式」 图片主体,细节词,修饰词 细节词可以任意组合,修饰词可以限定一种风格,也可以…

永恒之蓝 ms17-010

文章目录 永恒之蓝 ms17-0101. 漏洞介绍1.1 影响版本1.2 漏洞原理 2. 信息收集2.1 主机扫描2.2 端口扫描 3. 漏洞探测4. 漏洞利用5. 特殊情况5.1 安装wine32环境5.2 安装攻击32位操作系统所用的的脚本 永恒之蓝 ms17-010 很久之前做过的永恒之蓝漏洞… 1. 漏洞介绍 永恒之蓝…

【STM32】RCC时钟模块(使用HAL库)

https://gitee.com/linhir-linhir/stm32-f103-c8/blob/master/STM32%E6%9C%80%E6%96%B0%E5%9B%BA%E4%BB%B6%E5%BA%93v3.5/Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_rcc.h STM32最新固件库v3.5/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c…

Linux环境开发工具yum、makefile的使用 【Linux】

文章目录 Linux软件包管理器 - yumLinux下安装软件的方式yum查找软件包如何实现本地机器和云服务器之间的文件互传卸载软件Linux编译器 - gcc/g 程序的翻译过程1.预编译(预处理)2.编译(生成汇编)3.汇编(生成机器可识别…

MySQL数据库 #3

文章目录 一、创建表的完整语法二、约束条件1.unsigned (无符号)2. zerofill (0填充)3. default (默认值)4. not null(非空)5. unique(唯一)6. primary key &…

1024程序员节背后的秘密:1024程序员节的前世今生

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

中国艺术孙溟㠭篆刻《绕绕》

孙溟展先生现在的这方篆刻作品,没有使用大篆和小篆文字来篆刻,彰显篆刻的金石魅力。一改以往的不同,以圆形组合设计,用篆刻的刀法刻出,即体现篆刻的美,又达到了作者想表达的感情。这方篆刻作品溟展先生起名…

SD NAND

文章目录 前言SD NAND vs SD 卡SD NAND vs SPI NANDCS SD NAND 优势芯片介绍结构框图引脚介绍参考设计 焊接测速单片机读写测试作为 ARM Linux 系统盘使用 前言 提到 SD,最先想到的就是 SD 卡,由于体积关系,TF 卡使用得更为普遍,…

[Ubuntu 18.04] 搭建文件夹共享之Samba服务器

Samba是一个开源项目,允许Windows用户在Linux和Unix系统上进行文件共享。 Samba服务器是一个可以让Linux或Unix系统在网络上充当Windows NT/2000/XP/2003等网络操作系统的共享资源的软件。它允许用户通过SMB/CIFS协议在Linux或Unix系统与Windows共享资源。 Samba服务器的主要…

VRPTW(MATLAB):淘金优化算法GRO求解带时间窗的车辆路径问题VRPTW(提供参考文献及MATLAB代码)

一、VRPTW简介 带时间窗的车辆路径问题(Vehicle Routing Problem with Time Windows, VRPTW)是车辆路径问题(VRP)的一种拓展类型。VRPTW一般指具有容量约束的车辆在客户指定的时间内提供配送或取货服务,在物流领域应用广泛,具有重要的实际意义。VRPTW常…

ARM | 传感器必要总线IIC

IIC总线介绍 1.谈谈你对IIC总线理解? 1)IIC总线是串行半双工同步总线,主要用于连接整体电路 2)SCL/SDA作用:IIC是两线制,一根是时钟线SCK,用于控制什么时候进行进行数据传输,时钟信号由主机发出; 另一根是数据线SDA,用于进行数据传输,可以从…

垃圾收集器与内存分配策略

概述 垃圾收集需要完成的三件事情: 哪些内存需要回收?什么时候回收?如何回收? 判断对象是都存活的算法: 引用计数法:在对象中添加一个引用计数器,每当有一个地方引用时,计数器值就…

python基础教程:异常处理

嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 有时候我们在写程序的时候会出现错误或者异常,导致程序终止,如下这个例子: #!/usr/bin/env python a 2/0 print(a)结果提示如…

Visual Studio Professional 2019 软件安装教程(附安装包下载)

Microsoft Visual Studio 是一个非常强大的集成开发环境(IDE),适用于 Windows 上的 .NET 和 C 开发人员。它提供了一系列丰富的工具和功能,可以提升和增强软件开发的每个阶段。 Visual Studio IDE 是一个创意启动板,可…

C++ 多线程编程和同步机制:详解和实例演示

C中的多线程编程和同步机制使得程序员可以利用计算机的多核心来提高程序的运行效率和性能。本文将介绍多线程编程和同步机制的基本概念和使用方法。 多线程编程基础 在C中&#xff0c;使用<thread>库来创建和管理线程。线程可以通过函数、成员函数或者Lambda表达式来实现…

基于C#使用winform技术的游戏平台的实现【C#课程设计】

基于C#使用winform技术的游戏平台的实现【C#课程设计】 说明项目结构项目运行截图及实现的功能 部分代码一些说明(个人觉得一些难点的说明)一、ListView &#xff0c;ImageList 的综合使用二、图片上传以及picturebox 图片的动态替换三、图表插件的使用四、SQL工具类封装五、高…

最新哔哩哔哩邮箱绑定接口签名JS逆向分析

本章教程主要逆向分析 哔哩哔哩邮箱绑定接口biliCSRF 和mid 参数。 教程仅供学习参考,请勿滥用,由此带来的法律责任需由自己承担。 目录 一、接口参数分析 二、签名加密代码 三、滑块验证码 一

LabVIEW应用开发——控件的使用(四)

接上文&#xff0c;这篇介绍时间控件。 LabVIEW应用开发——控件的使用&#xff08;三&#xff09; 1、时间控件Time Stamp control 在日常软件开发场景中&#xff0c;时间也是一种常用的控件&#xff0c;用于表达当前时间的显示、对下设置时间、时间同步等等场景。LabVIEW专门…

Redis主从模式(一)----搭建主从结构并演示

目录 一, 主从模式 1.1 单个Redis服务器可能存在的问题 1.2 单点问题 1.3 什么是主从模式 概念 图示 二, 演示Redis的主从复制 2.1 Redis-server进程 2.2 建立复制 1. 首先将redis.conf配置文件复制一份并修改daemonize 为 yes 2.修改配置文件中的端口号 3. 分别在…