购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.14 自动化测试封装实战

很多初学者在进行自动化测试过程中,前期都会把测试脚本和元素写在一起。例如,针对一个测试项目,可以多次在页面上模拟用户单击和输入等操作。当开发者修改了代码后,元素位置发生改变,需要重新修改元素定位的语法。当在编写了大量测试用例的情况下,这种维护成本就变得越来越高。本节通过自动化测试脚本的封装实战来解决这一类问题的出现。

2.14.1 自动化封装实战(一)

以登录功能为例,一般登录的整个流程是不会变化的。例如,输入用户名和密码,单击“登录”按钮。但是对于用户名和密码,“登录”按钮对应的元素可能会出现变化。一种比较简单的方法是将登录流程的脚本封装定义为一个模板,当调用时,只需要对模板进行入参即可。先来看一个简单的线性脚本,示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By     # 导入By类
from selenium.webdriver.support.ui import WebDriverWait # 导入WebDriverWait类
from selenium.webdriver.support import expected_conditions as EC # 导入EC模块
import time
driver = webdriver.Chrome()               #  获取驱动
driver.get('https://www.gjfax.com/toLogin') # 登录测试项目
driver.refresh()
driver.implicitly_wait(30) 
driver.find_element_by_id('mobilePhone').send_keys('18513600×××') # 输入用户名
element = WebDriverWait(driver,10,0.5).until(EC.presence_of_element_located((By.ID, 
'password')))
element.send_keys('a123456')           # 显示等待输入密码
login_Btn = driver.find_element_by_id('loginBtn').click()     # 单击“登录”按钮
time.sleep(3)
driver.quit()

上面的测试代码是一个完整的登录流程。在测试代码中,不难发现测试数据、元素和操作流程都是放在一起的,这种方式非常不利于后期脚本的维护。对上面代码进行二次改造,示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By     # 导入By类
from selenium.webdriver.support.ui import WebDriverWait # 导入WebDriverWait类
from selenium.webdriver.support import expected_conditions as EC # 导入EC模块
import time
def Element_Locator(*new_loctor):
    '''重写find_element定位方法'''
    return driver.find_element(*new_loctor)
def input_username(username,*userLoctor):
    '''输入用户名'''
    return Element_Locator(*userLoctor).send_keys(username)
def input_password(password,*passwdLoctor):
    '''输入密码'''
    return Element_Locator(*passwdLoctor).send_keys(password)
def click_btn(*clickLoctor):
    '''单击“登录”按钮'''
    return Element_Locator(*clickLoctor).click()
def assert_Login_text(*assertText):
'''获取登录成功后的验证信息'''
    return Element_Locator(*assertText).text

上述代码对By类提供的find_element()方法进行二次封装,封装后的定位统一写法改为Element_Locator(),*idLoctor表示接收的参数是不固定的,注意,所有带*的默认参数在传递时要放在正常参数的后面。将输入用户名、输入密码、单击“登录”按钮和获取登录成功后的验证信息分别封装成了input_username()、input_password()、click_btn()和assert_Login_text()方法,示例如下:

if __name__ == '__main__':
    # 定位器
    user_loc = (By.ID,'mobilePhone')
    passwd_loc = (By.ID,'password')
    click_loc = (By.ID,'loginBtn')
    successLogin_loc = (By.CSS_SELECTOR,'a.fc-blue.mr-5')
    driver = webdriver.Chrome()      # 获取驱动
    driver.get('https://www.gjfax.com/toLogin')  # 获取测试网址
    driver.maximize_window()      # 最大化窗口
    time.sleep(3)
    driver.refresh()
    input_username('18513600×××',*user_loc)     # 输入用户名
    input_password('a123456',*passwd_loc)   # 输入密码
    click_btn(*click_loc)      # 单击“登录”按钮
    time.sleep(3)
    # 断言
    if assert_Login_text(*successLogin_loc) == '安全退出':
        print('测试用例通过!')
    else:
        print('测试用例失败!')
    driver.quit()
    dr.quit()  # 关闭

在测试用例中调用时,分别传入对应的元素和数据,最后对登录后的结果进行判断。

2.14.2 自动化封装实战(二)

针对2.14.1小节的代码,可进行代码重构,即把整个登录功能结合面向对象进行再次封装,示例如下:

from selenium import webdriver
from time import sleep
from selenium.webdriver.common.by import By  # 二次定位的By类
class GJsProject(object):
   def __init__(self):
      self.driver = webdriver.Chrome()      # 定义驱动
   def openbrowser(self,url):      # 定义基础操作
      self.driver.get(url)
      self.driver.maximize_window()
      sleep(2)
   def by_css(self,loc):
      '''重写css定位'''
      return self.driver.find_element(By.CSS_SELECTOR,loc)
   def click_login_btn(self,loc):     # 单击“登录”按钮
      self.by_css(loc).click()
   def input_username_Text(self,loc,text):   # 输入用户名
      self.by_css(loc).send_keys(text)
   def input_password_Text(self,loc,text):   # 输入密码
      self.by_css(loc).send_keys(text)
   def click_login_button(self,loc):      # 单击“登录”按钮
      self.by_css(loc).click()
   def assert_success_text(self,loc):     # 获取验证信息
      return self.by_css(loc).text    
   def logsys_gjs_action(self,loc):     # 退出系统
      self.by_css(loc).click()
      sleep(2)
      self.driver.quit()

openbrowser()方法用于获取地址、最大化窗口基础操作。对By类中的css定位重写为by_css()方法。将输入用户名、输入密码、单击“登录”按钮3个流程封装成单独的方法。assert_success_text()方法用于登录成功后返回文本信息,示例如下:

# 登录流程
   def login_gjs(self,url,loc1,loc2,username,loc3,password,loc4,loc5,exceptText,loc6):
      self.openbrowser(url)
      sleep(1)
      self.click_login_btn(loc1)
      sleep(1)
      self.input_username_Text(loc2,username)
      sleep(1)
      self.input_password_Text(loc3,password)
      sleep(1)
      self.click_login_button(loc4)
      sleep(1)
      if self.assert_success_text(loc5) == exceptText:  # 断言登录是否成功
         print('pass')
      else:
         print('fail')
      self.logsys_gjs_action(loc6)

将获取地址、最大化窗口、输入用户名、输入密码和获取验证信息等操作进一步封装为login_gjs()方法,这样做的好处是在调用时只需传入对应的元素和测试数据即可,示例如下: F9Vv9GzyV5SDJZTIiZfI0JmjZKcWvoBrLEDkiJwGluXg8/QF/z3ga18dxzgYuwQq

if __name__ == '__main__':
   t = GJs()
   url = 'https://www.gjfax.com/'   # 打开项目地址
   loc1 = "span.menubar-btn .fc-white"   # 定位器
   loc2 = "# mobilePhone"
   username = '18513600×××'
   loc3 = "# password"
   password = 'a123456'
   loc4 = "# loginBtn"
   loc5 = "a.fc-blue.mr-5" 
   exceptText = '安全退出'
   loc6 = "a.fc-blue.mr-5"
   # 调用登录方法
   t.login_gjs(url,loc1,loc2,username,loc3,password,loc4,loc5,exceptText,loc6)
点击中间区域
呼出菜单
上一章
目录
下一章
×