selenium+python自動化測試系列(一):登錄


    最近接手商城的項目,針對后台測試,功能比較簡單,但是流程比較繁多,涉及到前后台的交叉測試。在對整個項目進行第一輪測試完成之后,考慮以后回歸測試任務比較重,為了減輕回歸測試的工作量,所以考慮后台可以進行部分自動化測試。

    之前一個項目使用robotframework進行回歸測試,了解了python語言,所以這次就使用python+selenium進行自動化回歸測試了。

配置環境

  • python2.7
  • 運行工具pycharm2017

流程說明

登錄操作步驟說明

  1. 打開登錄url,如http://192.168.10.6/login
  2. 在用戶名輸入框中輸入登錄的用戶名,如test001
  3. 在密碼是輸入框中輸入密碼,如testgood001
  4. 點擊登錄頁面的登錄按鈕,
  5. 登錄成功頁面,斷言登錄成功

線性操作

根據上面的步驟提示下面代碼顯示登錄操作,如下

#coding=utf-8
from selenium import webdriver
import unittest
import sys
reload(sys)
sys.setdefaultencoding('utf8')
class TestLogin(unittest.TestCase):
# 指定瀏覽器
	def setUp(self):
		self.driver = webdriver.Firefox()
	# 打開url
		self.driver.get("http://192.168.10.6/login")

	# 登錄操作
	def test_login(self):
		title = self.driver.title
		print title
		now_url = self.driver.current_url
		print now_url
		username = "test001"
		password = "testgood001"
		# 執行登錄操作
		#用戶名的定位
		self.driver.find_element_by_id("username").clear()
		self.driver.find_element_by_id("username").send_keys(username)
		#密碼的定位
		self.driver.find_element_by_id("password").clear()
		self.driver.find_element_by_id("password").send_keys(password)
		# 點擊登錄
		self.driver.find_element_by_css_selector(".btn.btn-success.btn-block").click()
		# 登錄成功斷言
		login_name = self.driver.find_element_by_xpath('html/body/div[3]/div[2]/ul/li[1]/a/strong').text
		login_name = login_name.strip('您好:')
		assert login_name == username

	# 關閉瀏覽器
	def tearDown(self):
    		self.driver.quit()


if __name__ == "__main__":
unittest.main()

    上面代碼顯示的是登錄成功的正常用例;實際操作中,針對登錄不僅僅有正常用例,還有異常用例,如用戶名為空,密碼為空,用戶名錯誤,密碼錯誤等;我們不能一個用例編寫一個py文件,如果這樣操作從本質而言相反增加了工作量。

    既然問題出來了,那么如何解決這個問題呢?

    思路:針對登錄而言,所有的步驟都是一樣的,唯一不同的就是登錄的用戶名和密碼,所以我們可以封裝登錄步驟,然后只需要專注不同測試用例中的登錄的用戶名和密碼的驗證即可。

    這里為了后續測試的簡便,使用了selenium中的po模式,即針對每個功能的操作頁面進行封裝,而后在針對該頁面進行測試用例的編寫。如這里的登錄頁面,我們需要針對登錄頁面進行封裝操作,把登錄頁面中的用戶名、密碼和登錄按鈕的定位進行封裝,這樣用例中只關注輸入不同的用戶名和密碼進行驗證即可。

說明:

    這里瀏覽器的打開和關閉也進行了封裝,放在myunit.py中。

po模式設計

    整體設計的結構如圖所示

    models/driver.py中封裝了打開瀏覽器的操作,這里使用的火狐瀏覽器進行操作。代碼如下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from selenium.webdriver import Remote
from selenium import webdriver
import sys
# 啟動瀏覽器
reload(sys)
sys.setdefaultencoding('utf8')
def browser():
	driver = webdriver.Firefox()
	return driver


if __name__ == '__main__':
		dr = browser()
		dr.get("http://192.168.10.6/login")
		dr.quit()

    models/myunit.py中主要封裝了瀏覽器的啟動和關閉的操作,代碼如下

# -*-coding:utf-8-*-
# _author_ = "janehost"
import unittest,sys
from selenium import webdriver
from driver import browser
reload(sys)
sys.setdefaultencoding('utf8')

class MyTest(unittest.TestCase):
		def setUp(self):
    		self.driver = browser()
    		self.driver.implicitly_wait(10)
    		self.driver.maximize_window()

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


if __name__ == '__main__':
		unittest.main()

    models/function.py中主要封裝了截圖的操作方法,代碼參考如下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from selenium import webdriver
import os,sys
reload(sys)
sys.setdefaultencoding('utf8')
# 截圖函數
def insert_img(driver, file_name):
		base_dir = os.path.dirname(os.path.dirname(__file__))
		base_dir = str(base_dir)
		base_dir = base_dir.replace('\\', '/')
		base = base_dir.split('test_case')[0]
		file_path = base + "report/image/" + file_name
		driver.get_screenshot_as_file(file_path)


if __name__ == '__main__':
		driver = webdriver.Firefox()
		driver.get("http://192.168.10.6/login")
		insert_img(driver, 'login.jpg')
		driver.quit()

    下面就是po模式的重點,針對頁面的封裝,首先創建一個page頁面的基本頁面,page_obj\base.py代碼如下

# -*-coding:utf-8-*-
# _author_ = "janehost"


from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import sys
reload(sys)
sys.setdefaultencoding('utf8')
class Page(object):

'''
頁面基礎類,用於所有頁面的繼承
'''

	base_url = "http://192.168.10.6/login"

	def __init__(self, selenium_driver, base_url=base_url, parent=None):
	self.base_url = base_url
	self.driver = selenium_driver
	self.timeout = 30
	self.parent = parent

def _open(self, url):
	url = self.base_url + url
	self.driver.get(url)
	assert self.on_page(), 'Did not land on %s' % url

def open(self):
	self._open(self.url)

def on_page(self):
    #return (self.driver.current_url).encode('utf-8') == (self.base_url + self.url)
	return self.driver.current_url.encode('utf-8') == (self.base_url + self.url)

def find_element(self, *loc):
    # return self.driver.find_element(*loc)
	try:
	# 確保所有元素是可見的
	# 注意:以下入參為元組的元素,需要加*。python存在這種特性,就是將入參放在元組里。
	#WebDriverWait(self.driver,10).until(lambda driver: driver.find_element(*loc).is_displayed())
	# 注意:以下入參本身是元組,不需要加*
		WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc))
		return self.driver.find_element(*loc)
	except:
		print u"%s 頁面中未能找到 %s 元素"%(self, loc)

def find_elements(self, *loc):
	return self.driver.find_elements(*loc)

def script(self, src):
	return self.driver.execute_script(src)

def swtich_frame(self, loc):
	return self.driver.swith_to_frame(loc)

def send_keys(self, loc, value, clear_first=True, click_first=True):
	try:
	# getattr相當於self.loc
		loc = getattr(self, "_%s" % loc)
		if click_first:
			self.find_element(*loc).click()
		if clear_first:
			self.find_element(*loc).clear()
		self.find_element(*loc).send_keys(value)
	except ArithmeticError:
		print u"%s 頁面中未能找到 %s 元素" % (self, loc)

    登錄頁面元素的封裝page_obj\loginPage.py,代碼如下

# -*-coding:utf-8-*-
# _author_ = "janehost"
"""
思路:創建登錄頁面對象,對用戶登錄頁面上的用戶名/密碼輸入框、登錄按鈕和
提示信息等元素的定位進行封裝。
"""
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from base import Page
from time import sleep

class login(Page):

	'''
	用戶登錄界面
	'''
	url = '/'
	# 登錄用戶名的定位
	login_username_loc = (By.ID, 'username')
	# 登錄密碼的定位
	login_password_loc = (By.ID,'password')
	# 登錄按鈕的定位
	login_button_loc = (By.CSS_SELECTOR,'.btn.btn-success.btn-block')
	# 登錄錯誤提示的定位
	login_error_loc = (By.ID,'error_msg')
	# 登錄成功用戶名信息
	login_user_success_loc = (By.XPATH, 'html/body/div[3]/div[2]/ul/li[1]/a/strong')

	# 登錄用戶名
	def login_username(self, username):
		self.find_element(*self.login_username_loc).clear()
		self.find_element(*self.login_username_loc).send_keys(username)

	# 登錄密碼
	def login_password(self, password):
		self.find_element(*self.login_password_loc).clear()
		self.find_element(*self.login_password_loc).send_keys(password)

	# 登錄按鈕
	def login_button(self):
	self.find_element(*self.login_button_loc).click()

	# 統一登錄入口
	def user_login(self, username="testuser01", password="testgood001"):
	# 獲取用戶名和頁面登錄
		self.open()
		self.login_username(username)
		self.login_password(password)
		self.login_button()
		sleep(3)

	# 登錄錯誤提示信息
	def login_error_hint(self):
		return self.find_element(*self.login_error_loc).text

	# 登錄成功用戶名信息
	def login_user_success(self):
		#return self.find_element(*self.login_user_success_loc).text
		username = self.find_element(*self.login_user_success_loc).text
		username = username.strip('您好:')
		return username

    登錄測試用例信息test_case\login_sta.py,代碼如下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from time import sleep
import unittest, random, sys
from models import myunit, function
from page_obj.loginPage import login
sys.path.append("./models")
sys.path.append("./page_obj")
reload(sys)
sys.setdefaultencoding('utf8')
class loginTest(myunit.MyTest):

	'''
	測試用戶登錄
	'''

	def user_login_verify(self, username="", password=""):
		login(self.driver).user_login(username, password)

	def test_login1(self):
	'''用戶名、密碼為空登錄'''
		self.user_login_verify()
		po = login(self.driver)
		self.assertEqual(po.login_error_hint(), '用戶名或密碼不能為空')
		function.insert_img(self.driver, "user_pawd_empty.jpg")

	def test_login2(self):
	'''用戶名正確,密碼為空登錄驗證'''
		self.user_login_verify(username="ces")
		po = login(self.driver)
		self.assertEqual(po.login_error_hint(), "用戶名或密碼不能為空")
		function.insert_img(self.driver,"pawd_empty.jpg")

	def test_login3(self):
	'''用戶名為空,密碼正確'''
		self.user_login_verify(password="12334ddf")
		po = login(self.driver)
		self.assertEqual(po.login_error_hint(),"用戶名或密碼不能為空")
		function.insert_img(self.driver, "user_empty.jpg")

	def test_login4(self):
	'''用戶名和密碼不匹配'''
		character = random.choice('abcdefghijklmnopqrstuvwxyz')
		username = "sdw" + character
		self.user_login_verify(username=username, password="2sdfd")
		po = login(self.driver)
		self.assertEqual(po.login_error_hint(), "用戶名或密碼錯誤")
		function.insert_img(self.driver, "user_pass_error.jpg")

	def test_login5(self):
	'''用戶名、密碼正確'''
		self.user_login_verify(username="adtest" , password="4dscsdx")
		sleep(3)
		po = login(self.driver)
		self.assertEqual(po.login_user_success(), u'adtest')
		function.insert_img(self.driver, "user_pwd_true.jpg")


if __name__ == '__main__':
	unittest.main()

    這樣登錄的測試用例就完成了。使用po模式之后,如果頁面ui發生變化,我們只需要修改元素的定位方法,而不需要改動整個框架,相對而言比較快捷。

參考:

小小的博客 [http://www.cnblogs.com/xiaozhiblog/p/5378723.html]

selenium2 python自動化測試實戰(蟲師)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM