web自动化——测试用例的设计

web自动化——测试用例的设计

  • web测试用例
  • 用例编写常识
  • 用例编写原则
    • 用例前置条件
    • 代码示例——以腾讯课堂为例
      • 页面xpath
      • 页面操作类
      • 数据准备
      • 测试用例

web测试用例

  • 放在excel中,用例中应该包含:ID、用例名称、功能模块、前置条件、执行步骤和预期结果
  • 作自动化测试的时候,首要考虑的是用例的独立性,任何情况下都是可以直接执行的,不依赖与前后测试用例的执行或者测试环境的切换,因此为了维护用管理的独立性,需要每一条用例都打开一次浏览器,执行用例后直接关闭
  • 如果在保证测试用例互不影响的情况下,可以打开一次浏览器,执行多条用例来节约时间
  • web自动化测试,在写代码之前现将用例设计好并写出来,明确自己会写什么样的用例,需要用到什么样的功能,在封装页面的时候,第一阶段只封装我们需要用到的属性或页面功能,其他用不到的可以不编写。

用例编写常识

  • 不是所有的手工测试用例都要转换为自动化测试用例
  • 考虑到脚本的开发成本,不要选择流程太负责的用例,如果有必要,可以考虑流程拆分成多个用例来实现脚本
  • 选择的用例最好可以构建成场景,例如一个功能模块,分多个测试用例,多个测试用例使用同一个场景
  • 选择的用例开一带有目的性,例如:这比分是用例的冒烟测试,那部分是用例的回归测试等等,当然,会存在重叠的关系,如果当前用例能不能满足需求,那么唯有修改用例来适应脚本和需求
  • 选取的用例可以是你认为重读执行,很繁琐的部分,例如:字段验证、提示信息验证,这部分适用于回归测试
  • 选取的用例可以是主流程,这部分适用于冒烟测试
  • 自动化测试也可以用来配置检查、数据库检查,这一部分可能超过手工测试,算是拓展的一部分,项目负责人可以选择的增加
  • 平时在手工测试时,如果需要构建一些复杂的数据或者重复简单的机械的动作,告诉自动化脚本,让他来帮你,或许你的效率会因此提高

用例编写原则

  • 一个用例为一个场景,从用户登录系统到最终退出关闭浏览器
  • 一个用例只验证一个功能点,不要试图在用户登录系统后将所有的功能都验证一遍
  • 尽量少的编写逆向逻辑用例,一方面因为逆向逻辑用例很多(例如手机号输入错误就有好几种情况);另一方面,自动化测试脚本本身就比较脆弱,对于复杂的逆向逻辑用例的实现比较麻烦并且容易出错
  • 用例和用例之间,尽可能的避免依赖
  • 一条用例完成之后,需要对测试场景进行还原,避免影响其他测试用例的执行

用例前置条件

  • 要将编写的用例列出(什么形式都好)—— 包含:前置、步骤和断言
  • 需要明确涉及那些页面
  • 前置条件利用各种手段准备,获取数据的时候可以使用接口或去查数据库,建议修改数据的时候通过接口修改。接口查询也是最好的方式
  • 注意:用例的步骤和断言必须要走页面,不能走接口
  • 用例的前置条件,不能调用测试用例,建议调用页面行为
  • 公共数据中不仅仅可以放url,也可以将公用的数据放在里面

代码示例——以腾讯课堂为例

页面xpath

#登录界面
from selenium.webdriver.common.by import By

class LoginXpath:
    #登录按钮
    button_login = (By.XPATH,'//div[@id="js-mod-entry-index"]//a')
    #ifram定位
    iframe_xpath = (By.XPATH, '//div[@class="login-qq-iframe-wrap"]//iframe')
    #用户名或者密码登录
    user_pwd_login = (By.ID,"switcher_plogin")
    # 登录文本框
    user_text = (By.ID, 'u')
    # 验证码文本框
    pwd_text = (By.ID, 'p')
    # 登录按钮
    login_button = (By.ID, 'login_button')
    #文本框下的错误提示:
    text_error_mes =(By.ID, 'err_m')
    #用户名
    user_mes = (By.XPATH,'//a[text()="退出"]')
#登录成功后,网页元素
from selenium.webdriver.common.by import By

class UserPage:

    #文本搜索框
    class_search_text=(By.XPATH,'//*[@id="js_keyword"]')
    #查询按钮
    class_search_button = (By.XPATH,'//*[@id="js_search"]')
    #付费课程
    search_class = (By.XPATH,'//dl[@class="sort-nav-order sort-nav-order-my sort-nav-top js-sort-nav-top"]//a[@class="cur-top"]')
    #好评率
    search_order_by = (By.XPATH,'//dd[@id="auto-test-5"]//a')
    #课程卡片
    class_click = (By.XPATH,'//li[@class="course-card-item--v3 js-course-card-item "][1]')
#课程详情和支付界面
from selenium.webdriver.common.by import By

class ClassDetailsPage:

    buy_button = (By.XPATH,'//div[@id="js_btn_bar"]//*[@class="general-btn-txt institution-btn-txt"]')
    pay_button = (By.XPATH,'//*[@class="im-btn purchase-bottom-btn btn-default btn-m"]')
    commodity_order = (By.XPATH,'//*[@class="ep-order-tit"]//dt')

页面操作类

#登录功能相关
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from web_unittest.test_PO.class_test_datas.class_xpath_login import LoginXpath as LX
class Login:

    def __init__(self,driver):
        # 打开一个会话
        self.driver = driver

    def click_login_button(self):
        WebDriverWait(self.driver,40).until(
            EC.visibility_of_element_located(LX.button_login))
        # 这里是没有提示的,原因是diver是外部传进来的方法
        self.driver.find_element(*LX.button_login).click()

    def ifram_swith_and_click_user_pwd(self):
        WebDriverWait(self.driver,40).until(
            EC.frame_to_be_available_and_switch_to_it(LX.iframe_xpath))
        self.driver.find_element(*LX.user_pwd_login).click()

    def send_login_data(self,user,pwd):
        WebDriverWait(self.driver,40).until(
            EC.visibility_of_element_located(LX.user_text))
        self.driver.find_element(*LX.user_text).send_keys(user)
        self.driver.find_element(*LX.pwd_text).send_keys(pwd)
        self.driver.find_element(*LX.login_button).click()

    def error_msg(self):

        WebDriverWait(self.driver,40).until(
            EC.visibility_of_element_located(LX.text_error_mes))
        return self.driver.find_element(*LX.text_error_mes).text
#搜索课程,进入详情后支付
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from web_unittest.test_PO.class_test_datas.class_Xpath_user import UserPage as US
from web_unittest.test_PO.class_test_datas.class_class_details import ClassDetailsPage as CL
from web_unittest.test_PO.class_test_datas.class_xpath_login import LoginXpath as LX
class UserPage:

    def __init__(self,driver):
        self.dirver = driver

    def isExit_name(self):
        try:
            WebDriverWait(self.dirver, 40).until(
                EC.visibility_of_element_located(LX.user_mes))
            return True
        except:
            return False


    #查询课程
    def search_class(self,mes):
        time.sleep(5)
        #输入查询信息
        self.dirver.find_element(*US.class_search_text).send_keys(mes)
        #点击搜索
        self.dirver.find_element(*US.class_search_button).click()

    #等待查询结果,排序
    def isExitClass(self):
        WebDriverWait(self.dirver, 40).until(
            EC.visibility_of_element_located(US.search_class))
        self.dirver.find_element(*US.search_class).click()
        #滚动条滑动至元素可见
        element= self.dirver.find_element(*US.search_order_by)
        self.dirver.execute_script("arguments[0] .scrollIntoView();", element)
        #点击好评率
        element.click()

    #点击课程卡片,切换窗口
    def switch_alart(self):
        #获取新窗口出现前的句柄
        handles_list = self.dirver.window_handles
        #点击课程卡片
        self.dirver.find_element(*US.class_click).click()
        #等待新窗口出现
        WebDriverWait(self.dirver, 40).until(EC.new_window_is_opened(handles_list))  # 在handle中出现新的窗口
        #获取窗口句柄列表
        handles_list_new = self.dirver.window_handles
        #切换窗口
        self.dirver.switch_to.window(handles_list_new[-1])

        #点击购买按钮
    def click_buy(self):
        #等待购买按钮
        WebDriverWait(self.dirver, 40).until(
            EC.visibility_of_element_located(CL.buy_button))
        #点击
        self.dirver.find_element(*CL.buy_button).click()

    #点击支付按钮
    def click_pay(self):
        #等待支付按钮
        WebDriverWait(self.dirver, 40).until(
            EC.visibility_of_element_located(CL.pay_button))
        #点击
        self.dirver.find_element(*CL.pay_button).click()

    def isExit(self):
        #确认是否有待支付界面的元素
        try:
            WebDriverWait(self.dirver, 40).until(
                EC.visibility_of_element_located(CL.commodity_order))
            return True
        except:
            return False

数据准备

#公共数据
login_url = 'https://ke.qq.com/'
#测试数据
#登录成功的数据
login_success_datas = {"user":"XXX","pwd":"XXX"}


#登录失败的数据
login_fail_datas = [
{"user":"XXX","pwd":"","excpet":"你还没有输入密码!"} ,
{"user":"XXX","pwd":"XXX","excpet":"你输入的帐号或密码不正确,请重新输入。"},
]

测试用例

  • setUpClass和setUp在unittest中可以同时存在,运行的时候,先运行setUpClass
  • setUpClass在用例中只调用一次,setUp每条用例都会执行
  • 同理还有tearDown和tearDownClass
#购买课程相关用例
 @classmethod
    def setUpClass(cls):
        #预置条件中只需要准备一次的用例放在这里
        #添加课程——接口(有课程才能购买)
        #充值——接口(有钱才能买课程)——获取账号余额的时候,如果余额中存在单位,可以考虑split
        #链接数据库
        pass

    def setUp(self):
        # 打开一个会话
        self.driver = webdriver.Chrome()
        # 全屏
        self.driver.maximize_window()
        self.driver.get(CO.login_url)
        #登录每一次都要进行,所以放在setUp中
        user = Lo.login_success_datas.get("user")
        pwd = Lo.login_success_datas.get("pwd")
        Login(driver=self.driver).click_login_button()
        Login(driver=self.driver).ifram_swith_and_click_user_pwd()
        Login(driver=self.driver).send_login_data(user,pwd)

    def test_buy_class(self):
        #查询
        UserPage(self.driver).search_class("柠檬班")
        #查询课程存在
        UserPage(self.driver).isExitClass()
        #切换窗口
        UserPage(self.driver).switch_alart()
        #购买和支付
        UserPage(self.driver).click_buy()
        UserPage(self.driver).click_pay()
        #断言
        self.assertTrue(UserPage(self.driver).isExit())

    def tearDown(self):
        self.driver.quit()
    
    @classmethod
    def tearDownClass(cls):
        #只需要一次恢复环境的操作放这里
        #删除课程——接口(有课程才能购买)
        #断开数据库
        pass
import unittest
from selenium import webdriver
from web_unittest.test_PO.page_object.class_login_page import Login
from web_unittest.test_PO.page_object.class_user_page import UserPage
from web_unittest.test_PO.class_test_datas import test_common_data as CO
from web_unittest.test_PO.class_test_datas import class_login_data as Lo
from ddt import ddt,data

@ddt
class TestLogin(unittest.TestCase):

    def setUp(self):
        # 打开一个会话
        self.driver = webdriver.Chrome()
        # 全屏
        self.driver.maximize_window()
        self.driver.get(CO.login_url)

    #登录成功
    def test_login_success(self):
        #在本页面打开会话,将diver传入页面page的初始化函数中,调用的时候直接传入
        user = Lo.login_success_datas.get("user")
        pwd = Lo.login_success_datas.get("pwd")
        Login(driver=self.driver).click_login_button()
        Login(driver=self.driver).ifram_swith_and_click_user_pwd()
        Login(driver=self.driver).send_login_data(user,pwd)
        self.assertTrue(UserPage(driver=self.driver).isExit_name())

    #登录失败——没有密码
    @data(*Lo.login_fail_datas)
    def test_login_no_pwd(self,datas):
        user = datas.get("user")
        pwd = datas.get("pwd")
        excpet = datas.get("excpet")
        Login(driver=self.driver).click_login_button()
        Login(driver=self.driver).ifram_swith_and_click_user_pwd()
        Login(driver=self.driver).send_login_data(user,pwd)
        actual = Login(driver=self.driver).error_msg()
        self.assertEqual(excpet,actual)


    def tearDown(self):
        self.driver.quit()

你可能感兴趣的:(python,web测试,自学python)