Selenium2+Python自動化測試實戰

     本人在網上查找了不少作自動化的教程和實例,偶然的一個機會接觸到了selenium,以爲很是好用。後來就在網上查閱各類selenium的教程,可是網上的東西真的是太多了,以致於不少東西參考完後沒法系統的學習和應用,有一次在網上隨意搜索,找到了-蟲師-寫的《Selenium2自動化測試實戰基於Python語言》,以爲真心不錯,內容也很調理,爲了方便本身學習和知識的整理,就把其中蟲師編寫的自動化項目教程整理一下,有興趣的能夠去參看蟲師的博客http://www.cnblogs.com/fnng/javascript

如下整理的只是書中自動化項目的知識內容,介紹怎麼搭建自動化測試框架、執行自動化測試用例、生成自動化測試報告、發送測試報告郵件....,具體的Selenium和python語言基礎不作介紹html

1、項目結構介紹java

 下面逐級介紹此目錄與文件的做用node

mztstpro/python

|-----bbs/web

|       |-----data/chrome

|       |-----report/瀏覽器

|                |------image/服務器

|       |-----test_case/架構

|                |------models/

|                         |----driver.py

|                         |----function.py

|                         |----myunit.py

|                |------page_obj/

|                         |----*Page.py

|                |------*_sta.py

|-----driver/

|-----package/

|-----run_bbs_test.py

|-----startip.bat

|-----自動化測試項目說明文檔.docx

1.mztestpro測試項目

bbs:用於存放BBS項目的測試用例、測試報告和測試數據等。

driver:用於存放瀏覽器驅動。如selenium-server-standalone-2.47.0jar、chromedriver.exe、IEDriverServer.exe等。在執行測試前根據執行場景將瀏覽器驅動複製到系統環境path目錄下。

package:用於存放自動化所用到的擴展包。例如:HTMLTestRunner.py屬於一個單獨模塊

run_bbs_test.py:項目主程序。用來運行社區(BBS)自動化用例。

startup.bat:用於啓動selenium server,默認啓動driver目錄下的selenium-server-standalone-2.44.0.jar。

自動化測試項目說明文檔.docx:介紹當前項目的架構、配置和使用說明。

2.bbs目錄

data:該目錄用來存放測試相關數據。

report:用於存放HTML測試報告。其下面建立了image目錄用於存放測試過程當中的截圖。

test_case:測試用例目錄,用於存放測試用例及相關模塊。

3.test_case

models:該目錄下存放了一些公共的配置函數及公共類。

page_obj:該目錄用於存放測試用例的頁面對象(Page Object)。根據自定義規則,以「*Page.py」命名的文件爲封裝的頁面對象文件。

*_sta.py:測試用例文件。根據測試文件匹配規則,以「*_sta.py」命名的文件被看成自動化測試用例執行。

2、編寫公共模塊

  首先定義驅動文件:

  ...\mztestpro\bbs\test_case\models\driver.py

driver.py

# __author__ = 'Ztiny'
# -*-coding:utf-8-*-

from selenium.webdriver import Remote
from selenium import webdriver

# 啓動瀏覽器驅動
def browser():
    driver = webdriver.Firefox()
    # host = '192.168.0.132:5555' #運行主機 :端口號(默認本機:127.0.0.1:4444)
    # dc = {'browserName':'internet explorer','version':'','platfrom':'WINDOWS','javascriptEnabled':True}
    # # dc = {'browserName':'firefox','version':'','platfrom':'ANY','javascriptEnabled':True,'marionette':False,}#指定瀏覽器 ('chrome','firefox')
    # driver = Remote(command_executor='http://' + host + '/wd/hub',
    #                 desired_capabilities=dc)
    return driver

if __name__ == '__main__':
    dr = browser()
    dr.get("http://www.mayi.com")
    dr.quit()

 

  定義瀏覽器驅動函數browser(),該函數能夠進行配置,根據咱們的須要,配置測試用例在不一樣的主機及瀏覽器下運行。

  自定義測試框架類:

  ...\mztestpro\bbs\test_case\models\myunit.py

 myunit.py

# __author__ = 'Ztiny'
#-*-coding:utf-8-*-
from selenium import webdriver
from driver import browser
import unittest

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()

 

  定義MyTest()類用於集成unittest.TestCase類,由於筆者建立的全部測試類中setUp()與tearDown()方法所作的事情相同,因此,將他們抽象爲MyTest()類,好處就是在編寫測試用例時再也不考慮這兩個方法的實現。

  定義截圖函數:

  ...\mztestpro\bbs\test_case\models\function.py

function.py

# __author__ = 'Ztiny'
#-*-coding:utf-8-*-

from selenium import webdriver
import os

#截圖函數
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.Ie()
    driver.get("http://www.baidu.com")
    insert_img(driver,'baidu.jpg')
    driver.quit()

  建立截圖函數insert_img(),爲了保持自動化項目的移植性,採用相對路徑的方式將測試截圖保持到.\report\image目錄中。

3、編寫Page Object

  首先建立基礎Page基礎類(百度主頁爲例):
  ...\mztestpro\bbs\test_case\page_obj\base.py

base.py

# __author__ = 'Ztiny'
#-*-coding:utf-8-*-

class Page(object):
    '''
    頁面基礎類,用於全部頁面的繼承
    '''

    baidu_url = 'https://www.baidu.com'

    def __init__(self,selenium_driver,base_url = baidu_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 find_element(self,*loc):
        return self.driver.find_element(*loc)

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

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

    def on_page(self):
        return (self.driver.current_url).encode('utf-8') == (self.base_url + self.url)
def script(self,src): return self.driver.execute_script(src)

   建立頁面基礎類,經過__init__()方法初始化參數:瀏覽器驅動、URL地址、超時時長等。定義基本方法:open()用於打開BBS地址:find_element()和find_elements()分別用來定位單個與多個元素;建立script()方法能夠更簡便地調用JavaScript代碼。固然還能夠對更多的WebDriver方法進行重定義。

   建立BBS登陸對象類:

   ...\mztestpro\bbs\test_case\page_obj\loginPage.py

loginPage.py

# __author__ = 'Ztiny'
# -*-coding:utf-8-*-

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 = '/'

    #Action
    baidu_login_user_loc = (By.LINK_TEXT,u'登陸')

    #彈出登陸窗口
    def baidu_login(self):
        self.find_element(*self.baidu_login_user_loc).click()

    login_username_loc = (By.ID,'TANGRAM__PSP_8__userName')
    login_password_loc = (By.ID,'TANGRAM__PSP_8__password')
    login_button_loc = (By.ID,'TANGRAM__PSP_8__submit')

    #登陸用戶名
    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="**********@qq.com", password="*********"):
        '''獲取用戶名和麪登陸'''
        self.open()
        self.baidu_login()
        self.login_username(username)
        self.login_password(password)
        self.login_button()
        sleep(2)
user_error_hint_loc
= (By.LINK_TEXT,u"帳號不能爲空") pawd_error_hint_loc = (By.LINK_TEXT,u"密碼不能爲空") user_login_success_loc = (By.LINK_TEXT,u'Ztiny') #用戶名錯誤提示 def user_error_hint(self): return self.find_element(*self.user_error_hint_loc).text #密碼錯誤提示 def pawd_error_hint(self): return self.find_element(*self.pawd_error_hint_loc).text #登陸成功用戶名 def user_login_success(self):
return self.find_element(*self.user_login_success_loc).text

   建立登陸頁面對象,對用戶登陸頁面上的用戶名/密碼輸入框、登陸按鈕和提示信息等元素的定位進行封裝。除此以外,還建立user_login()方法做爲系通通一登陸的入口。關於對操做步驟的封裝能夠放在Page Object當中,也能夠放在測試用例當中,這個主要根據具體的需求來衡量。這裏之因此要放在Page Object當中,主要考慮到還會有其餘的測試用例調用到該登陸方法。爲username 和 password 入參數設置了默認值是爲了方便其餘用例在調用user_login()時不用再傳遞登陸用戶信息,由於該系統大多用例的執行使用該帳號便可,同時也方便了在帳號失效時的修改。

4、編寫測試用例

   如今開始編寫測試用程序,由於前面已經作好了基礎工做,此時測試用例的編寫將會簡單的許多,更能集中精力考慮用例的設計和事項。

   建立BBS登陸類:

   ...\mztestpro\bbs\test_case\login_sta.py

 此處須要注意文件名的建立。例如,假設登陸頁的對象命名爲loginPage.py,那麼關於測試登陸的用例文件應該命名爲login_sta.py,這樣方便後期用例報錯時問題跟蹤。儘可能把一個頁面上的元素定位封裝到一個「*Page.py」文件中,把針對這個頁面的測試用例集中到一個「*_sta.py」文件中

login_sta.py

# __author__ = 'Ztiny'
#-*-coding:utf-8-*-

from time import sleep
import unittest, random ,sys
sys.path.append("./models")
sys.path.append("./page_obj")
from models import myunit, function
from page_obj.loginPage import login

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.user_error_hint(),"帳號不能爲空") self.assertEqual(po.pawd_error_hint()."密碼不能爲空") function.insert_img(self.driver,"user_pawd_empty.jpg") def test_login2(self): '''用戶名正確,密碼爲空登陸''' self.user_login_verify(username="*******") po = login(self.driver) self.assertEqual(po.pawd_error_hint(),"密碼不能爲空") function.insert_img(self.driver,"paqd_empty.jpg") def test_login3(self): '''用戶名爲空,密碼正確''' self.user_login_verify(password="*******") po = login(self.driver) self.assertEqual(po.user_error_hint(),"帳號不能爲空") function.insert_img(self.driver,"user_empty.jpg") def test_login4(self): '''用戶名與密碼不匹配''' character = random.choice('abcdefghijklmnopqrstuvwxyz') username = "zhangsan" + character self.user_login_verify(username=username,password="123456") po = login(self.driver) self.assertEqual(po.pawd_error_hint(),"密碼與帳號不匹配") function.insert_img(self.driver,"user_pwad_error.jpg") def test_login5(self): '''用戶名、密碼正確''' self.user_login_verify(username='********@qq.com',password='********') sleep(2) po = login(self.driver) self.assertEqual(po.user_login_success(), u'Ztiny') function.insert_img(self.driver ,"user_pwd_ture.jpg") if __name__ == '__main__': unittest.main()

   首先建立loginTest()類,繼承myunit.Mytest()類,關於Mytest()類的實現,請翻看前面代碼。這樣就省去了在每個測試類中實現一遍setUp()和tearDown()方法。

   建立user_login_verify()方法,並調用loginPage.py中定義的user_login()方法。爲何不直接調用呢?由於user_login()的入參已經設置了默認值,緣由前面已經解釋,這裏須要從新將其入參的默認值設置爲空便可。

   前三條測試用例很好理解,分別驗證:

  • 用戶名密碼爲空,點擊登陸
  • 用戶名正確,密碼爲空,點擊登陸
  • 用戶名爲空,密碼正確,點擊登陸   

 第四條用例驗證錯誤用戶名和密碼登陸。在當前系統中若是反覆使用固定錯誤的用戶名和密碼,系統會彈出驗證碼輸入框。爲了不這種狀況的發生,就須要用戶名進行隨機變化,此處的作法用固定前綴「zhangsan」,末尾字符從a~z中隨機一個字符與前綴進行拼接。

   第五條用例驗證正確的用戶名和密碼登陸,經過獲取用戶名做爲斷言信息

   在上面的測試用例中,每條測試用例結束時都調用function.py文件中的insert_img函數進行截圖。當用例運行完成後,打開...\report\image\目錄將會看到用例執行的截圖文件,如圖:

5、執行測試用例

   爲了在測試用例運行過程當中不影響作其餘事,筆者選擇調用遠程主機或虛擬機來運行測試用例,那麼這裏就須要使用Selenium Grid(其包含Selenium Server)來調用遠程節點。

   建立...\mztestpro\startup.bat文件,用於啓動...\mztestpro\driver\目錄下的Selenium Server。

startup.bat

@echo off
echo 啓動hub
java -jar .\mztestpro\driver\selenium-server-standalone-2.40.0.jar -role hub -host 192.168.0.102 -port 4444
echo 啓動node
java -jar .\mztestpro\driver\selenium-server-standalone-2.40.0.jar -role node -port 5555 -hub  http://192.168.0.102:4444/grid/register

 

   雙擊startup.bat文件,啓動Selenium Server建立主hub節點。在遠程主機或虛擬機中通樣須要啓動Selenium Server建立node節點。

   建立用例執行程序:...\mztestpro\run_bbs_test.py

run_bbs_test.py

# __author__ = 'Ztiny'
#-*-coding:utf-8-*-

from HTMLTestRunner import HTMLTestRunner
from email.mime.text import MIMEText
import smtplib
import unittest
import time
import os
# =========================郵件接收者============================
mailto_list=["********@qq.com"]
#============= 設置服務器,用戶名、口令以及郵箱的後綴===============
mail_host="smtp.163.com"
mail_user="******@163.com"
mail_pass="*******"
#===========================發送郵件============================
def send_mail(to_list,file_new):
    '''''
    to_list:發給誰
    sub:主題
    content:內容
    send_mail("aaa@126.com","sub","content")
    '''
    f = open(file_new, 'rb')
    mail_body = f.read()
    f.close()
    me=mail_user
    msg = MIMEText(mail_body,'html','utf-8')
    msg['Subject'] = u'自動化測試報告'
    msg['From'] = me
    msg['To'] = ";".join(to_list)
    try:
        s = smtplib.SMTP()
        s.connect(mail_host,25)
        s.login(mail_user,mail_pass)
        s.sendmail(me, to_list, msg.as_string())
        s.close()
        return True
    except Exception, e:
        print str(e)
        return False

#==============查找測試報告目錄,找到最新生成的測試報告文件==========
def new_report(testreport):
    lists = os.listdir(testreport)
    lists.sort(key=lambda fn:os.path.getatime(testreport + "\\" + fn))
    file_new = os.path.join(testreport,lists[-1])
    print(file_new)
    return file_new

if __name__ == '__main__':
    now = time.strftime("%Y-%m-%d %H_%M_%S")
    filename = './bbs/report/' + now +'result.html'
    fp = open(filename,'wb')
    runner = HTMLTestRunner(stream=fp,
                            title=u'百度登陸自動化測試報告',
                            description=u'環境 :window 7 瀏覽器:firefox')
    discover = unittest.defaultTestLoader.discover('./bbs/test_case',
                                                   pattern='*_sta.py')
    runner.run(discover)
    fp.close()
    file_path = new_report('./bbs/report/')

    if send_mail(mailto_list,file_path):
        print u"發送成功"
    else:
        print u"發送失敗"

 

   執行過程當中並無任何改動,集成HTMLTestRunner生成的HTML測試報告,以及集成自動發郵件功能等。惟一須要注意的是,腳本中的路徑建議使用相對路徑,以便於項目被移動到任意目錄下執行。

   打開...\mztestpro\driver.py 文件,修改腳本運行的節點及瀏覽器。如今能夠經過運行run_bbs_test.py來執行測試項目了。

小結:

   若是你完成了前面的操做,那麼這只是自動化項目的開始,不過,咱們已經把基本架構設計完成,後面大部分工做就是編寫各個頁面的*Page.py以及測試用*_sta.py。在這個過程當中會遇到各類各樣的問題,如元素定位、架構的擴展,須要讀者本身去克服這些問題。

PS:對自動化感興趣的同窗能夠加QQ羣:539725853,歡迎加入交流!

轉載請註明出處:http://www.cnblogs.com/xiaozhiblog/p/5378723.html

相關文章
相關標籤/搜索