1、PO模式的思想

  1. 原理:
    1. 将页面的元素定位和元素行为封装成一个page类
    2. 类的属性:元素的定位
    3. 类的行为:元素的操作 
  2. 页面对象和测试用例分离
  3. 测试用例:
    1. 调用所需要页面对象中的行为,组成测试用例
    2. 测试用例中,只需要含有页面函数的调用和断言,不应该出现元素定位等其他的操作,如果写测试用例中出现需要其他的额外的操作,可以想办法封装到页面对象或者元素定位中
  4. 好处:
    1. 当某个页面的元素发生变化,只需要修改该页面对象中的代码即可,测试用例不需要修改
    2. 提高代码的重用率,结构清晰,维护代码容易
    3. 测试用例发生变化是,不需要或者只需要修改少数页面对象代码即可

2、使用unittest框架实现PO模式

  1. 新建一个包,命名为PageObjects,包中用来封装各个页面的功能
    1. 页面对象封装的类中,函数用来实现页面的功能,在类的初始化函数中,使用传参(driver)的方式完成,页面只需要实现对应功能即可,具体传入什么样的测试,在测试用例的前置条件中实现,可以提高函数的重用率
      1. 页面对象封装函数
         from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.common.by import By
        class LoginPage:
        def __init__(self,driver):
        self.driver=driver def login(self,username,pwd,remember_user=True):
        # 等待定位元素出现
        WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.XPATH,"//input[@name='phone']")))
        # 输入用户名
        self.driver.find_element_by_xpath("//input[@name='phone']").send_keys(username)
        # 输入密码
        self.driver.find_element_by_xpath("//input[@name='password']").send_keys(pwd)
        # 定位记住手机号元素
        remember_ele=self.driver.find_element_by_xpath("//input[@name='remember_me']")
        # 判断时候记住手机号
        if remember_user==True:
        remember_ele.checked=True
        else:
        remember_ele.checked=False
        # 点击登录
        self.driver.find_element_by_xpath("//button[text()='登录']").click()
      2. 测试用例调用页面对象函数,代码如下

        1     def test_login_success(self):
        2 # 2、步骤
        3 # 实例化LoginPage类
        4 lg=LoginPage(self.driver)
        5 # 调用login方法
        6 lg.login("登录账号","登录密码")
        7 # 3、断言
        8 self.assertTrue(IndexPage(self.driver).isExist_logout_ele())
      3. Index_page页面封装函数代码
        from selenium.webdriver.support import expected_conditions as EC
        from selenium.webdriver.support.wait import WebDriverWait
        from selenium.webdriver.common.by import By
        class IndexPage:
        def __init__(self,driver):
        self.driver=driver def isExist_logout_ele(self):
        try:
        WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.XPATH,"//a[text()='退出']")))
        return True
        except:
        return False
      4. 测试用例的前置条件代码
        import unittest
        from selenium import webdriver
        from PageObjects.login_page import LoginPage
        from PageObjects.index_page import IndexPage
        class TestLogin(unittest.TestCase): def setUp(self):
        # 1、前置条件
        url="http://ip:host/Index/login.html"
        self.driver=webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.get(url)
      5. 运行测试用例可以在测试用例最后面使用一下代码,然后运行该代码
        if __name__ == '__main__':
        unittest.main()
      6. 运行结果如下,表示运行成功 
  2. 新建一个包,命名为TestCases,包中用来写测试用例,测试用例中用到那个页面对象中的函数时,只需要调用页面对象中的函数就可以了
  3. 新建一个包,命名为TestDatas,用来写测试数据,将测试数据的类导入到测试用例模块中,进行使用,这样的话,测试数据便于管理,测试数据添加、修改、删除不用修改测试用例
    1. 在TestCases下面新建一个公用的数据管理.py文件Common_Datas.py和模块数据的.py文件login_datas.py,如下t图:

      #Common_Datas.py
      web_login_url="http://ip:port/Index/login.html" #login_datas.py
      #正常场景---测试数据
      success_data={"user":"","pwd":""} # 异常用例--手机号格式不正确(大于11位,小于11位,为空,不在号码段)
      error_data=[
      {"user": "", "pwd": "","check":"请输入正确的手机号"},
      {"user": "", "pwd": "","check":"请输入正确的手机号"},
      {"user": "", "pwd": "","check":"请输入正确的手机号"},
      {"user": "", "pwd": "","check":"请输入手机号"},
      {"user": "", "pwd": "","check":"请输入密码"},
      {"user": "", "pwd": "","check":"请输入手机号"},
      ]
    2. 在测试用例模块使用数据管理模块中的数据
       import unittest
      from selenium import webdriver
      from PageObjects.login_page import LoginPage
      from PageObjects.index_page import IndexPage
      from TestDatas import Common_Datas as CD
      from TestDatas import login_datas as ld
      from ddt import ddt,data @ddt
      class TestLogin(unittest.TestCase):
      @classmethod
      def setUpClass(cls):
      # 1、前置条件
      cls.driver=webdriver.Chrome()
      cls.driver.maximize_window()
      cls.driver.get(CD.web_login_url)
      # 实例化LoginPage类
      cls.lg=LoginPage(cls.driver)
      @classmethod
      def tearDownClass(cls):
      cls.driver.quit() def tearDown(self):
      self.driver.refresh()
      pass
      # 正常用例--登录成功
      def test_login_1_success(self):
      # 2、步骤 # 调用login方法
      self.lg.login(ld.success_data['user'],ld.success_data['pwd'])
      # 3、断言
      self.assertTrue(IndexPage(self.driver).isExist_logout_ele())
      # 异常用例--手机号码格式不正确(大于11位,小于11位,为空,不在号码段) ddt
      @data(*ld.error_data)
      def test_login_0_user_wrongFormat(self,item):
      self.lg.login(item['user'],item['pwd'])
      self.assertEqual(self.lg.get_errorMsg_form_loginArea(),item['check'])

      备注:

      setUpClass(cls)函数和tearDownClass(cls)只在整个用例开始和结束时运行一次,必须使用@classmethod来修饰,如上面的异常测试用例有6条,在用例开始前和结束时只运行一次 
      setUp(self)函数和tearDown(self)在每个测试用例开始和结束时运行,如果使用这两个函数,上面的6条用例,每运行一个,就会运行一次这两个函数,总共运行6次
      tearDown(self)可以和setUpClass(cls)函数和tearDownClass(cls)函数结合使用,如上面的界面刷新self.driver.refresh()和页面关闭cls.driver.quit()
    3. 测试用例类型相同的测试数据可以设计在一起,使用ddt在测试用例运行时分别执行测试用例
    4. 使用unittest框架,运行测试用例,如下:
       import unittest
      from TestCases.test_login import TestLogin
      from HTMLTestRunnerCN import HTMLTestReportCN
      # 创建一个容器,用来存测试用例
      suite=unittest.TestSuite()
      # 加载测试用例的类的实例
      loader=unittest.TestLoader()
      # 将测试用例加载到suite容器中
      suite.addTest(loader.loadTestsFromTestCase(TestLogin))
      # 打开文件,用来写测试报告
      with open("test_result.html",'wb') as file: # runner=unittest.TextTestRunner(verbosity=1) runner=HTMLTestReportCN( stream=file, verbosity=2, title="web自动化测试", description="第一个web自动化测试", tester="wsk")
      # 运行测试用例
      runner.run(suite)
    5. 运行结果,如下图:

      在写测试用例时,如果使用unittest框架可以使用函数名来控制代码的执行顺序,如:

      ok test_login_0_user_wrongFormat_6 (TestCases.test_login.TestLogin)  --------------------  0  
      ok test_login_1_success (TestCases.test_login.TestLogin)------------------------------------------1    前面都一样,0比1小,先运行

  

web自动化测试中的PO模式(一)的更多相关文章

  1. web自动化测试中绕开验证码登陆的方式

    web自动化测试中登陆需验证码是很大的一个困扰.现推荐一种简单的避开验证码登陆的方式,先代码进入登录页,人工输入验证码登录后浏览器自动保存cookie,再在新的标签中登录. 具体代码如下: publi ...

  2. python web自动化测试中失败截图方法汇总

    在使用web自动化测试中,用例失败则自动截图的网上也有,但实际能落地的却没看到,现总结在在实际应用中失败截图的几种方法: 一.使用unittest框架截图方法:   1.在tearDown中写入截图的 ...

  3. JavaScript在web自动化测试中的作用

    前言 JS的全称JavaScript,是一种运行在浏览器中的解释型脚本语言,通常用来实现web前端页面的基本功能,对于前端开发人员是不得不掌握的一门基本技能,但是对于做web自动化测试的人员来说,如果 ...

  4. 说说UI自动化中的PO模式

    PO模式,全称PageObject模式,即页面对象模式.将页面定位与业务操作分离. po模式有以下几个优点: 1.易读性好 2.扩展性高 3.复用性强 4.维护性好 5.代码冗余率低 了解了po模式及 ...

  5. TestNG测试框架在基于Selenium进行的web自动化测试中的应用

    转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ TestNG+Selenium+Ant TestNG这个测试框架可以很好的和基于Selenium的 ...

  6. (转)Web自动化测试中的接口测试

    1.背景 1.1 Web程序中的接口 1.1.1 典型的Web设计架构 web是实现了基于网络通信的浏览器客户端与远程服务器进行交互的应用,通常包括两部分:web服务器和web客户端.web客户端的应 ...

  7. Web自动化测试中的接口测试

    1.2.3 接口可测性分析 接口显而易见要比UI简单的都,只需要知道协议和参数即可完成一次请求,从自动化测试实施难易程度来看,有以下几个特征: 1)驱动执行接口的自动化成本不高:HTTP,RPC,SO ...

  8. 高访问量WEB开发中的架构模式,学习从点滴开始

     当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要在Web系统架构 ...

  9. 对web应用中单一入口模式的理解及php实现

    在我们web应用的开发中,经常会听见或看见单一入口模式,在我开始学习tp框架的时候也不理解为什么要运用一个单一入口模式,只是会使用,最近自己在搞一个小东西的时候才明白为什么在web开发中要运用单一入口 ...

随机推荐

  1. SOFARPC模式下的Consul注册中心

    Consul大家不陌生,就是和Zookeeper.Nacos一伙的,能够作为微服务基础架构的注册中心,算是比较成熟的组件,和Springcloud集成顺滑, 考虑到Eureka已经停止更新,所以有必要 ...

  2. python中可变长度参数详解

    1. *args用法:python会将所有位置的参数收集到一个元组中 2. **args用法:python会将关键字参数传递给一个新的字典.**允许将关键字参数转换为字典 用法见如下代码: def f ...

  3. 关于Quartz .NET(V3.0.7)的简要说明

    目录 0. 任务调度 1. Quartz .NET 1.1 基本概念 1.2 主要接口和对象 2. 使用示例 2.0 准备工作 2.1 每间隔一定时间间隔执行一次任务 2.3 某天的固定时间点执行任务 ...

  4. 【转】不怕难之BlockingQueue及其实现

    1. 前言 BlockingQueue即阻塞队列,它是基于ReentrantLock,依据它的基本原理,我们可以实现Web中的长连接聊天功能,当然其最常用的还是用于实现生产者与消费者模式,大致如下图所 ...

  5. python 顺序读取文件夹下面的文件(自定义排序方式)

    我们在读取文件夹下面的文件时,有时是希望能够按照相应的顺序来读取,但是 file_lists=os.listdir()返回的文件名不一定是顺序的,也就是说结果是不固定的.就比如读取下面这些文件,希望能 ...

  6. python3爬虫爬取金庸小说所有角色

    # -*- coding:utf-8 -*- import requests from bs4 import BeautifulSoup url = 'http://www.jinyongwang.c ...

  7. 图-连通分量-DFS-749. 隔离病毒

    2020-03-17 21:56:20 问题描述: 病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒. 假设世界由二维矩阵组成,0 表示该区域未感染病毒,而 1 表示该区域已感染病毒.可 ...

  8. BIT-Reverse Pairs

    2019-12-17 11:07:02 问题描述: 问题求解: 本题可以看作是逆序数问题的强化版本,需要注意的是num[i] > 2 * num[j],这里有0和负数的情况. public in ...

  9. 曹工说Spring Boot源码(27)-- Spring的component-scan,光是include-filter属性的各种配置方式,就够玩半天了.md

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  10. Android菜单(menu)

    Android  菜单 我们继续来进行学习,今天写一下在软件中用的还算较多的菜单. 1.Menu 菜单,很显然,作用就是点击不同的选项触发不同的方法.现在在安卓使用中推荐使用ActionBar,但这里 ...