page object——页面代码解耦
登入网易云音乐账户,从首页到登入框…到手机登入框,里面会经历好多个界面,通过对每个页面进行page object,降低页面与页面之间关联度,为后续代码修改,定位到修改提供便利。
testcase代码,test_login.py
通过测试用例,可以清晰知道每个页面中对应的每一个步骤。
#coding:utf-8
import unittest
from wangyi_music_web_pageobject import WangYiMusic
from ddt import ddt,data,unpack,file_data
from selenium import webdriver
@ddt
class TestLogin(unittest.TestCase):
@data(('https://music.163.com/','165564999840654','huudff',u'请输入正确的手机号'),('https://music.163.com/','15970456721','mimacuowula',u'该手机号尚未注册'))
@unpack
def test_login_wangyiyun(self,url,phone_number,password,expext_result):
print ('input phone number:{}'.format(phone_number))
print ('input password:{}'.format(password))
print ('expect result:{}'.format(expext_result.encode('utf-8')))
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(4)
self.driver.maximize_window()
open_wangyi_music = WangYiMusic(self.driver)
home_page = open_wangyi_music.enter_home_page(url)
scan_or_other_login_page = home_page.click_login()
login_mode_page = scan_or_other_login_page.select_other_login_mode()
login_mode_page.check_privacy_policy_checkout()
phone_number_login = login_mode_page.phone_number_login()
phone_number_login.input_phone_number_account(phone_number)
phone_number_login.input_password(password)
phone_number_login.click_login_button()
actual_login_result = phone_number_login.get_actual_login_status()
#self.assertTrue(expext_result == actual_login_result, 'Test Failed') #断言
if expext_result.encode('utf-8') == actual_login_result:
print ('Test Pass')
else:
print ('Test Failed,actual_login_result:{}'.format(actual_login_result))
phone_number_login.close_window()
页面代码,wangyi_music_web_pageobject.py
#coding: utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class WangYiMusic(object):
_login_locator = (By.CSS_SELECTOR, 'a.link.s-fc3')
_other_login_mode_locator =(By.CSS_SELECTOR ,'a.u-btn2.other')
_phone_number_login_locator = (By.CSS_SELECTOR ,'a.u-btn2.u-btn2-2')
_privacy_policy_checkout_loactor = (By.CSS_SELECTOR ,'input#j-official-terms')
_input_phone_number_locator = (By.CSS_SELECTOR , 'input.j-phone.txt.u-txt')
_input_password_locator = (By.CSS_SELECTOR , 'input#pw.j-pwd.u-txt')
_login_button_locator = (By.CSS_SELECTOR, 'a.j-primary.u-btn2.u-btn2-2')
_locate_mark_locator = (By.CSS_SELECTOR, 'i.u-icn.u-icn-25')
_get_login_failed_reason_locator = (By.CSS_SELECTOR,'div.j-err.u-err span')
def __init__(self,driver):
self.driver = driver
def enter_home_page(self,url):
self.driver.get(url)
return HomePage(self.driver)
class HomePage(WangYiMusic):
def click_login(self):
self.driver.find_element(*self._login_locator).click()
return ScanOrOtherPage(self.driver)
class ScanOrOtherPage(HomePage):
_other_login_mode_locator =(By.CSS_SELECTOR ,'a.u-btn2.other')
def select_other_login_mode(self):
self.driver.find_element(*self._other_login_mode_locator).click()
return LoginModePage(self.driver)
class LoginModePage(ScanOrOtherPage):
def check_privacy_policy_checkout(self):
if not self.driver.find_element(*self._privacy_policy_checkout_loactor).is_selected():
self.driver.find_element(*self._privacy_policy_checkout_loactor).click()
def phone_number_login(self):
self.driver.find_element(*self._phone_number_login_locator).click()
return PhoneNumberLoginPage(self.driver)
class PhoneNumberLoginPage(LoginModePage):
def input_phone_number_account(self,phone_number):
self.driver.find_element(*self._input_phone_number_locator).send_keys(phone_number)
def input_password(self,password):
self.driver.find_element(*self._input_password_locator).send_keys(password)
def click_login_button(self):
self.driver.find_element(*self._login_button_locator).click()
def get_login_failed_reason(self):#查看页面上登入失败的原因
#self.driver.implicitly_wait(5)
time.sleep(5)
return self.driver.find_element(*self._get_login_failed_reason_locator).text.encode('utf-8')
def get_actual_login_status(self): #主要是看账户登入真实情况
if self.driver.find_element(*self._locate_mark_locator).is_displayed: #如果页面上显示出!
return self.get_login_failed_reason() #打印登入失败的原因
else:
return '登入成功' #否则登入成功
def close_window(self):
self.driver.quit()
2.excel——测试用例、测试数据、测试结果整合
将手工测试用例、测试数据,测试结果存放到同一个excel。
excel表格:包含测试用例、测试数据、测试结果
load_data.py
#coding=utf-8
import xlrd
import openpyxl
#负责读取数据
class GetTestData():
def __init__(self):
self.excel = xlrd.open_workbook('test_report.xlsx') #如果xlrd 2.×的版本,是不支持xlsx格式的excel,故需要安装旧版的1.2.0
self.sheet = self.excel.sheet_by_name('test_data')
self.rows = self.sheet.nrows
self.cols = self.sheet.ncols
@property
def get_test_data(self):
data_list = []
data = []
for row in range(1,self.rows):
for i in self.sheet.row_values(row,1,5):
if type(i) == float: #表格中输入的手机号码是float类型,需要转换成int,不然会报错
data.append(int(i)) #用data列表存放转换后的每组测试数据
else:
data.append(i)
data_list.append(data)
data =[] #移除测试数据
return data_list #获取url,phone_number,password,expext_result列的数据,返回一个list
def test_result(self):
for row in range(1,self.rows):
self.sheet.cell_value(row,7)
#写入测试用例
class TestResult():
def __init__(self):
self.excel = openpyxl.load_workbook('test_report.xlsx')
self.sheet = self.excel['test_data']
self.num = 2
self.result = 2
def write_actual_result(self,actual_result):#写入页面上的实际提示的结果
self.sheet.cell(row=self.num,column=6,value=actual_result)
self.num +=1
self.close_excel()
def write_test_result(self,test_result): #写入测试结果
self.sheet.cell(row=self.result,column=7,value=test_result)
self.result +=1
self.close_excel()
def close_excel(self):
self.excel.save('test_report.xlsx')
网页代码: wangyi_music_web_pageobject.py
#coding: utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
class WangYiMusic(object):
_login_locator = (By.CSS_SELECTOR, 'a.link.s-fc3')
_other_login_mode_locator =(By.CSS_SELECTOR ,'a.u-btn2.other')
_phone_number_login_locator = (By.CSS_SELECTOR ,'a.u-btn2.u-btn2-2')
_privacy_policy_checkout_loactor = (By.CSS_SELECTOR ,'input#j-official-terms')
_input_phone_number_locator = (By.CSS_SELECTOR , 'input.j-phone.txt.u-txt')
_input_password_locator = (By.CSS_SELECTOR , 'input#pw.j-pwd.u-txt')
_login_button_locator = (By.CSS_SELECTOR, 'a.j-primary.u-btn2.u-btn2-2')
_locate_mark_locator = (By.CSS_SELECTOR, 'i.u-icn.u-icn-25')
_get_login_failed_reason_locator = (By.CSS_SELECTOR,'div.j-err.u-err span')
def __init__(self,driver):
self.driver = driver
def enter_home_page(self,url):
self.driver.get(url)
return HomePage(self.driver)
class HomePage(WangYiMusic):
def click_login(self):
self.driver.find_element(*self._login_locator).click()
return ScanOrOtherPage(self.driver)
class ScanOrOtherPage(HomePage):
_other_login_mode_locator =(By.CSS_SELECTOR ,'a.u-btn2.other')
def select_other_login_mode(self):
self.driver.find_element(*self._other_login_mode_locator).click()
return LoginModePage(self.driver)
class LoginModePage(ScanOrOtherPage):
def check_privacy_policy_checkout(self):
if not self.driver.find_element(*self._privacy_policy_checkout_loactor).is_selected():
self.driver.find_element(*self._privacy_policy_checkout_loactor).click()
def phone_number_login(self):
self.driver.find_element(*self._phone_number_login_locator).click()
return PhoneNumberLoginPage(self.driver)
class PhoneNumberLoginPage(LoginModePage):
def input_phone_number_account(self,phone_number):
self.driver.find_element(*self._input_phone_number_locator).send_keys(phone_number)
def input_password(self,password):
self.driver.find_element(*self._input_password_locator).send_keys(password)
def click_login_button(self):
self.driver.find_element(*self._login_button_locator).click()
def get_login_failed_reason(self):#查看页面上登入失败的原因
#self.driver.implicitly_wait(5)
time.sleep(2)
return self.driver.find_element(*self._get_login_failed_reason_locator).text.encode('utf-8')
def get_actual_login_status(self): #主要是看账户登入真实情况
if self.driver.find_element(*self._locate_mark_locator).is_displayed: #如果页面上显示出!
return self.get_login_failed_reason() #打印登入失败的原因
else:
return '登入成功' #否则登入成功
def close_window(self):
self.driver.quit()
测试用例,test_login.py
#coding:utf-8
import unittest
from wangyi_music_web_pageobject import WangYiMusic
from ddt import ddt,data,unpack,file_data
from selenium import webdriver
from load_data import GetTestData,TestResult
get_test_data = GetTestData()
write_test_result = TestResult()
test_data_list = get_test_data.get_test_data
@ddt
class TestLogin(unittest.TestCase):
@data(*test_data_list)
@unpack
def test_login_wangyiyun(self,url,phone_number,password,expext_result):
print ('input phone number:{}'.format(phone_number))
print ('input password:{}'.format(password))
print ('expect result:{}'.format(expext_result.encode('utf-8')))
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(4)
self.driver.maximize_window()
open_wangyi_music = WangYiMusic(self.driver)
home_page = open_wangyi_music.enter_home_page(url)
scan_or_other_login_page = home_page.click_login()
login_mode_page = scan_or_other_login_page.select_other_login_mode()
login_mode_page.check_privacy_policy_checkout()
phone_number_login = login_mode_page.phone_number_login()
phone_number_login.input_phone_number_account(phone_number)
phone_number_login.input_password(password)
phone_number_login.click_login_button()
actual_login_result = phone_number_login.get_actual_login_status()
if expext_result.encode('utf-8') == actual_login_result:
write_test_result.write_test_result('Pass')
else:
write_test_result.write_test_result('Fail')
write_test_result.write_actual_result(actual_login_result)
phone_number_login.close_window()
if __name__ =='__main__':
unittest.main()
测试结果:
test_report.xlsx