目的:使用Python的selenium库模拟浏览器的操作(如定位元素,用户输入,点击等),使用unittest来实现case的封装,参数化,测试日志生成等功能(后续通过jenkins集成,交付,部署)
使用到的库:selenium, unittest, xmlrunner
方法:创建项目selenium_unittest,并在项目下创建主目录autotest_frame, 在autotest_frame下创建包baseframe,pageobject,testsuites(baseframe包用来存放浏览器基类,定义浏览器的一些通用操作,如浏览器对象创建,元素查找,用户输入,元素点击等,pageobject包存放需要测试的子类,这里我们使用百度和搜狗首页作为测试对象,主要定义了登录功能的实现,如果需要测试其他页面可另外定义对应的页面子类,最后testsuites包存放对应的测试用例,并定义了测试前置、后置条件,断言等)
**pycharm中运行时,直接运行testsuites包中的testcases模块,不能使用unittest方式运行
1. 创建浏览器基类basepage.py
code:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage(object):
def __init__(self):
self.driver = webdriver.Chrome()
def wait_time(self):
time.sleep(5)
def open_page(self, url):
self.driver.get(url)
self.driver.maximize_window()
def close_page(self):
self.driver.quit()
def find_element(self, selector):
method = selector[0]
value = selector[1]
#通过id, name, classname, xpath方式来定位需要操作的元素并返回,使用WebDriverWait防止元素未定位完成就执行后续的操作
if method in 'id' or 'name' or 'class' or 'xpath':
if method == 'id':
element = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.ID, value)))
elif method == 'name':
element = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.NAME, value)))
elif method == 'class':
element = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, value)))
elif method == 'xpath':
element = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, value)))
else:
print ('no element found')
return element
else:
print ('search method error')
#定位元素并模拟输入
def send_key_to_element(self, selector, value):
element = self.find_element(selector)
try:
element.send_keys(value)
except Exception:
print ('input error occurred')
#定位元素模拟点击
def click_element(self, selector):
element = self.find_element(selector)
try:
element.click()
except Exception:
print ('click element error')
2. 在pageobject包中创建需要测试的页面子类(这里以模拟百度首页登录为例,baidu_login_page.py), 如果需要测试百度首页其他内容可在BaiduLoginPage类中定义。如果需要测试其他页面,需要创建对应新的页面子类
code:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from baseframe.basepage import BasePage
class BaiduLoginPage(BasePage):
def __init__(self):
BasePage.__init__(self)
self.baseUrl = 'https://www.baidu.com'
#封装需要的页面元素
#首页登录按钮xpath
self.homePageloginButton = ["xpath", "//*[@id='u1']/a[@name='tj_login']"]
#弹窗从扫描切换到“用户名登录”按钮
self.userNameloginButton = ["xpath", "//*[@id='TANGRAM__PSP_10__footerULoginBtn']"]
#弹窗“手机/邮箱/用户名”输入框
self.userNameInput = ["xpath", "//*[@id='TANGRAM__PSP_10__userName']"]
#弹窗“密码”输入框
self.userPasswordInput = ["xpath", "//*[@id='TANGRAM__PSP_10__password']"]
#弹窗“登录”按钮
self.userLoginButton = ["xpath", "//*[@id='TANGRAM__PSP_10__submit']"]
#登录后页面展示现实账号
self.logged_username = ["xpath", "//*[@id='s_username_top']/span[@class='username']"]
#定义用户登录方法
def userLogin(self, username, password):
self.open_page(self.baseUrl)
self.click_element(self.homePageloginButton)
self.click_element(self.userNameloginButton)
self.send_key_to_element(self.userNameInput, username)
self.send_key_to_element(self.userPasswordInput, password)
self.click_element(self.userLoginButton)
username = self.find_element(self.logged_username).get_attribute()
res = 0 if username == "eps2012" else 1
self.close_page()
return res
class SogouLoginPage(BasePage):
def __init__(self):
BasePage.__init__(self)
self.baseUrl = 'https://pinyin.sogou.com/'
#首页登录按钮链接
self.homePageloginButton = ["xpath", "//*[@id='user_info']/ul/li[2]/div[1]/a"]
#弹窗用户名输入框
self.userNameInput = ["xpath", "//*[@onfocus='psfocus(1);']"]
#弹窗密码输入框
self.userPasswordInput = ["xpath", "//*[@onfocus='psfocus(3);']"]
#弹窗登录按钮
self.loginBtn = ["xpath", "//*[@class='btn_bar']/table/tbody/tr/td[2]/input"]
#登录完成页面用户名
self.loggedUsername = ["xpath", "//*[@id='user_info']/ul/li[2]/div[1]/a"]
def userLogin(self, username, password):
self.open_page(self.baseUrl)
self.click_element(self.homePageloginButton)
self.send_key_to_element(self.userNameInput, username)
self.send_key_to_element(self.userPasswordInput, password)
self.click_element(self.loginBtn)
self.wait_time()
name = self.find_element(self.loggedUsername).text
if username in name:
res = 0
else:
res = 1
self.wait_time()
self.close_page()
return res
3. 在testsuites包中创建测试用例并添加到测试集中:
code:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pageobject.test_page import BaiduLoginPage
from pageobject.test_page import SogouLoginPage
import unittest
import xmlrunner
import sys
reload(sys)
class WebTests(unittest.TestCase):
@classmethod
def setUp(self):
print ("-----test beginning------")
@classmethod
def tearDown(self):
print ("-----test ending-----")
def test_baidu_login(self):
#创建测试对象子类
bdLogin = BaiduLoginPage()
#创建断言来判断是否登录成功
self.assertEqual(0, bdLogin.userLogin('*******', '*********'))
def test_sogou_login(self):
sgLogin = SogouLoginPage()
self.assertEqual(0, sgLogin.userLogin('***********', '********'))
if __name__ == "__main__":
testSuites = unittest.TestSuite()
testSuites.addTest(WebTests('test_sogou_login'))
#这里使用xml来作为日志输出的文本格式,并保存在本地目录
runner = xmlrunner.XMLTestRunner(output='c:/test_logs/', verbosity=2)
runner.run(testSuites)