国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全)

這篇具有很好參考價(jià)值的文章主要介紹了Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

?? 視頻學(xué)習(xí):文末有免費(fèi)的配套視頻可觀看

???關(guān)注公眾號(hào)【互聯(lián)網(wǎng)雜貨鋪】,回復(fù) 1?,免費(fèi)獲取軟件測(cè)試全套資料,資料在手,漲薪更快

今天來(lái)說(shuō)說(shuō)pytest吧,經(jīng)過(guò)幾周的時(shí)間學(xué)習(xí),有收獲也有疑惑,總之最后還是搞個(gè)小項(xiàng)目出來(lái)證明自己的努力不沒(méi)有白費(fèi)

環(huán)境準(zhǔn)備

1 ? ?確保您已經(jīng)安裝了python3.x
2 ? ?配置python3+pycharm+selenium2開(kāi)發(fā)環(huán)境 ? ?
3 ? ?安裝pytest庫(kù)pip install pytest
4 ? ?安裝pytest -html 報(bào)告插件pip install pytest-html
5 ? ?安裝pypiwin32庫(kù)(用來(lái)模擬按鍵)pip install pypiwin32
6 ? ?安裝openpyxl解析excel文件庫(kù)pip install openpyxl
7 ? ?安裝yagmail發(fā)送報(bào)告庫(kù)pip install yagmail
8 ? ?確保已配置火狐或谷歌瀏覽器及對(duì)應(yīng)驅(qū)動(dòng) ?
9 ? ?確保已經(jīng)正確配置好發(fā)送郵件的郵箱

項(xiàng)目簡(jiǎn)介

測(cè)試地址

https://mail.126.com

測(cè)試范圍

1.126電子郵箱登錄功能測(cè)試-驗(yàn)證正確帳號(hào)密碼登錄成功-驗(yàn)證錯(cuò)誤用戶名密碼登錄失敗(有很多情況,用例里面做了充分的校驗(yàn))

2.126電子郵箱添加聯(lián)系人功能測(cè)試-驗(yàn)證正確填寫必填項(xiàng)數(shù)據(jù)添加聯(lián)系人成功-驗(yàn)證缺省必填項(xiàng)數(shù)據(jù)添加聯(lián)系人失敗-驗(yàn)證必填項(xiàng)字段數(shù)據(jù)格式錯(cuò)誤添加聯(lián)系人失敗

3.126電子郵箱發(fā)送郵件功能測(cè)試-驗(yàn)證普通郵件發(fā)送成功-驗(yàn)證帶附件郵件發(fā)送成功

項(xiàng)目設(shè)計(jì)

1.python編程語(yǔ)言設(shè)計(jì)測(cè)試腳本

2.webdriver驅(qū)動(dòng)瀏覽器并操作頁(yè)面元素

3.二次封裝webdriver Api 操作方法

4.采用PageObject設(shè)計(jì)模式,設(shè)計(jì)測(cè)試業(yè)務(wù)流程

5.通過(guò)UI對(duì)象庫(kù)存儲(chǔ)頁(yè)面操作元素

6.通過(guò)數(shù)據(jù)文件存儲(chǔ)數(shù)據(jù),讀取數(shù)據(jù),參數(shù)化測(cè)試用例并驅(qū)動(dòng)測(cè)試執(zhí)行

7.通過(guò)第三方插件pytest-html生成測(cè)試報(bào)告

8.通過(guò)yagmail第三方庫(kù),編寫發(fā)送報(bào)告接口,測(cè)試工作完成后自動(dòng)發(fā)送測(cè)試報(bào)告

目錄結(jié)構(gòu)

?1?PytestAutoTestFrameWork
?2?|—|config
?3?|——|__init__.py
?4?|——|conf.py
?5?|——|config.ini
?6?|—|data
?7?|——|__init__.py
?8?|——|tcData.xlsx
?9?|—Page
10?|——|PageObject.py
11?|———|__init__.py
12?|———|ContactPage.py
13?|———|HomePage.py
14?|———|LoginPage.py
15?|———|SendMailPage.py
16?|——|__init__.py
17?|——|BasePage.py
18?|—|report
19?|—|TestCases
20?|——|__init__.py
21?|——|conftest.py
22?|——|test_confactCase.py
23?|——|test_loginCase.py
24?|——|test_sendMailCase.py
25?|—|util
26?|——|__init__.py
27?|——|clipboard.py
28?|——|keyboard.py
29?|——|parseConFile.py
30?|——|parseExcelFile.py
31?|——|sendMailForReport.py
32?|—|conftest.py
33?|—|pytest.ini
34?|—|RunTestCase.py

代碼實(shí)現(xiàn)

通過(guò)126郵箱測(cè)試范圍分析,我們需要通過(guò)設(shè)計(jì)剪切板,模擬鍵盤完成附件上傳操作,因此我們首先來(lái)編寫這兩個(gè)方法
clipboard.py-操作剪切板

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/15?12:04
?4?@Auth?:?linux超
?5?@File?:?clipboard.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?win32con
11?import?win32clipboard?as?WC
12?
13?
14?class?ClipBoard(object):
15?????'''設(shè)置剪切板內(nèi)容和獲取剪切板內(nèi)容'''
16?
17?????@staticmethod
18?????def?getText():
19?????????'''獲取剪切板的內(nèi)容'''
20?????????WC.OpenClipboard()
21?????????value?=?WC.GetClipboardData(win32con.CF_TEXT)
22?????????WC.CloseClipboard()
23?????????return?value
24?
25?????@staticmethod
26?????def?setText(value):
27?????????'''設(shè)置剪切板的內(nèi)容'''
28?????????WC.OpenClipboard()
29?????????WC.EmptyClipboard()
30?????????WC.SetClipboardData(win32con.CF_UNICODETEXT,?value)
31?????????WC.CloseClipboard()
32?
33?
34?if?__name__?==?'__main__':
35?????from?selenium?import?webdriver
36?
37?????value?=?'python'
38?????driver?=?webdriver.Firefox()
39?????driver.get('http://www.baidu.com')
40?????query?=?driver.find_element_by_id('kw')
41?????ClipBoard.setText(value)
42?????clValue?=?ClipBoard.getText()
43?????query.send_keys(clValue.decode('utf-8'))

keyboard.py-模擬鍵盤

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/15?12:05
?4?@Auth?:?linux超
?5?@File?:?keyboard.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?
11?#?模擬按鍵
12?import?win32api
13?import?win32con
14?import?time
15?
16?
17?class?KeyBoard(object):
18?????"""模擬按鍵"""
19?????#?鍵盤碼
20?????vk_code?=?{
21?????????'enter'?:?0x0D,
22?????????'tab'?:?0x09,
23?????????'ctrl'?:?0x11,
24?????????'v'?:?0x56,
25?????????'a'?:?0x41,
26?????????'x'?:?0x58
27?????}
28?
29?????@staticmethod
30?????def?keyDown(key_name):
31?????????"""按下鍵"""
32?????????key_name?=?key_name.lower()
33?????????try:
34?????????????win32api.keybd_event(KeyBoard.vk_code[key_name],?0,?0,?0)
35?????????except?Exception?as?e:
36?????????????print('未按下enter鍵')
37?????????????print(e)
38?
39?????@staticmethod
40?????def?keyUp(key_name):
41?????????"""抬起鍵"""
42?????????key_name?=?key_name.lower()
43?????????win32api.keybd_event(KeyBoard.vk_code[key_name],?0,?win32con.KEYEVENTF_KEYUP,?0)
44?
45?????@staticmethod
46?????def?oneKey(key):
47?????????"""模擬單個(gè)按鍵"""
48?????????key?=?key.lower()
49?????????KeyBoard.keyDown(key)
50?????????time.sleep(2)
51?????????KeyBoard.keyUp(key)
52?
53?????@staticmethod
54?????def?twoKeys(key1,?key2):
55?????????"""模擬組合按鍵"""
56?????????key1?=?key1.lower()
57?????????key2?=?key2.lower()
58?????????KeyBoard.keyDown(key1)
59?????????KeyBoard.keyDown(key2)
60?????????KeyBoard.keyUp(key1)
61?????????KeyBoard.keyUp(key2)
62?
63?
64?if?__name__?==?'__main__':
65?????from?selenium?import?webdriver
66?????driver?=?webdriver.Firefox()
67?????driver.get('http://www.baidu.com')
68?????driver.find_element_by_id('kw').send_keys('python')
69?????KeyBoard.twoKeys('ctrl',?'a')
70?????KeyBoard.twoKeys('ctrl',?'x')

通過(guò)測(cè)試項(xiàng)目設(shè)計(jì),我們需要把測(cè)試數(shù)據(jù)存放在Excel文件中,把頁(yè)面操作元素存在UI對(duì)象庫(kù)中也就是一個(gè)配置文件,那么我們需要對(duì)Excel 和 ini文件解析,因此我們開(kāi)始編寫這兩個(gè)方法,設(shè)計(jì)UI對(duì)象庫(kù)和測(cè)試數(shù)據(jù)文件
parseExcelFile.py-解析Excel文件

?1?"""
??2?------------------------------------
??3?@Time?:?2019/4/22?16:12
??4?@Auth?:?linux超
??5?@File?:?parseExcelFile.py
??6?@IDE??:?PyCharm
??7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
??8?------------------------------------
??9?"""
?10?from?openpyxl?import?load_workbook
?11?from?config.conf?import?excelPath
?12?
?13?
?14?class?ParseExcel(object):
?15?
?16?????def?__init__(self):
?17?????????self.wk?=?load_workbook(excelPath)
?18?????????self.excelFile?=?excelPath
?19?
?20?????def?getSheetByName(self,?sheetName):
?21?????????"""獲取sheet對(duì)象"""
?22?????????sheet?=?self.wk[sheetName]
?23?????????return?sheet
?24?
?25?????def?getRowNum(self,?sheet):
?26?????????"""獲取有效數(shù)據(jù)的最大行號(hào)"""
?27?????????return?sheet.max_row
?28?
?29?????def?getColsNum(self,?sheet):
?30?????????"""獲取有效數(shù)據(jù)的最大列號(hào)"""
?31?????????return?sheet.max_column
?32?
?33?????def?getRowValues(self,?sheet,?rowNum):
?34?????????"""獲取某一行的數(shù)據(jù)"""
?35?????????maxColsNum?=?self.getColsNum(sheet)
?36?????????rowValues?=?[]
?37?????????for?colsNum?in?range(1,?maxColsNum?+?1):
?38?????????????value?=?sheet.cell(rowNum,?colsNum).value
?39?????????????if?value?is?None:
?40?????????????????value?=?''
?41?????????????rowValues.append(value)
?42?????????return?tuple(rowValues)
?43?
?44?????def?getColumnValues(self,?sheet,?columnNum):
?45?????????"""獲取某一列的數(shù)據(jù)"""
?46?????????maxRowNum?=?self.getRowNum(sheet)
?47?????????columnValues?=?[]
?48?????????for?rowNum?in?range(2,?maxRowNum?+?1):
?49?????????????value?=?sheet.cell(rowNum,?columnNum).value
?50?????????????if?value?is?None:
?51?????????????????value?=?''
?52?????????????columnValues.append(value)
?53?????????return?tuple(columnValues)
?54?
?55?????def?getValueOfCell(self,?sheet,?rowNum,?columnNum):
?56?????????"""獲取某一個(gè)單元格的數(shù)據(jù)"""
?57?????????value?=?sheet.cell(rowNum,?columnNum).value
?58?????????if?value?is?None:
?59?????????????value?=?''
?60?????????return?value
?61?
?62?????def?getAllValuesOfSheet(self,?sheet):
?63?????????"""獲取某一個(gè)sheet頁(yè)的所有測(cè)試數(shù)據(jù),返回一個(gè)元祖組成的列表"""
?64?????????maxRowNum?=?self.getRowNum(sheet)
?65?????????columnNum?=?self.getColsNum(sheet)
?66?????????allValues?=?[]
?67?????????for?row?in?range(2,?maxRowNum?+?1):
?68?????????????rowValues?=?[]
?69?????????????for?column?in?range(1,?columnNum?+?1):
?70?????????????????value?=?sheet.cell(row,?column).value
?71?????????????????if?value?is?None:
?72?????????????????????value?=?''
?73?????????????????rowValues.append(value)
?74?????????????allValues.append(tuple(rowValues))
?75?????????return?allValues
?76?
?77?
?78?if?__name__?==?'__main__':
?79?????#?excel?=?ParseExcel()
?80?????#?sheet?=?excel.getSheetByName('login')
?81?????#?print('行號(hào):',?excel.getRowNum(sheet))
?82?????#?print('列號(hào):',?excel.getColsNum(sheet))
?83?????#
?84?????#?rowvalues?=?excel.getRowValues(sheet,?1)
?85?????#?columnvalues?=?excel.getColumnValues(sheet,?2)
?86?????#?valueofcell?=?excel.getValueOfCell(sheet,?1,?2)
?87?????#?allvalues?=?excel.getAllValuesOfSheet(sheet)
?88?????#
?89?????#?print('第{}行數(shù)據(jù){}'.format(1,?rowvalues))
?90?????#?print('第{}列數(shù)據(jù){}'.format(2,?columnvalues))
?91?????#?print('{}{}單元格的內(nèi)容{}'.format(1,?2,?valueofcell))
?92?????#?print('login{}'.format(allvalues))
?93?
?94?????excel?=?ParseExcel()
?95?????sheet?=?excel.getSheetByName('mail')
?96?????print('行號(hào):',?excel.getRowNum(sheet))
?97?????print('列號(hào):',?excel.getColsNum(sheet))
?98?
?99?????allvalues?=?excel.getAllValuesOfSheet(sheet)
100?
101?????print('sendmail{}'.format(allvalues))

parseConFile.py-解析配置文件

1?"""
?2?------------------------------------
?3?@Time?:?2019/4/18?10:54
?4?@Auth?:?linux超
?5?@File?:?parseConFile.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?configparser
11?from?config.conf?import?configDir
12?
13?
14?class?ParseConFile(object):
15?
16?????def?__init__(self):
17?????????self.file?=?configDir
18?????????self.conf?=?configparser.ConfigParser()
19?????????self.conf.read(self.file,?encoding='utf-8')
20?
21?????def?getAllSections(self):
22?????????"""獲取所有的section,返回一個(gè)列表"""
23?????????return?self.conf.sections()
24?
25?????def?getAllOptions(self,?section):
26?????????"""獲取指定section下所有的option,?返回列表"""
27?????????return?self.conf.options(section)
28?
29?????def?getLocatorsOrAccount(self,?section,?option):
30?????????"""獲取指定section,?指定option對(duì)應(yīng)的數(shù)據(jù),?返回元祖和字符串"""
31?????????try:
32?????????????locator?=?self.conf.get(section,?option)
33?????????????if?('->'?in?locator):
34?????????????????locator?=?tuple(locator.split('->'))
35?????????????return?locator
36?????????except?configparser.NoOptionError?as?e:
37?????????????print('error:',?e)
38?????????return?'error:?No?option?"{}"?in?section:?"{}"'.format(option,?section)
39?
40?????def?getOptionValue(self,?section):
41?????????"""獲取指定section下所有的option和對(duì)應(yīng)的數(shù)據(jù),返回字典"""
42?????????value?=?dict(self.conf.items(section))
43?????????return?value
44?
45?
46?if?__name__?==?'__main__':
47?????cf?=?ParseConFile()
48?????print(cf.getAllSections())
49?????print(cf.getAllOptions('126LoginAccount'))
50?????print(cf.getLocatorsOrAccount('126LoginAccount',?'username'))
51?????print(cf.getOptionValue('126LoginAccount'))

config.ini

1?[126LoginAccount];126郵箱正確的登錄賬號(hào)和密碼;運(yùn)行用例時(shí)請(qǐng)更換正確的用戶名和密碼
?2?username=linuxxiaochao
?3?password=xiaochao11520
?4?[HomePageElements];126郵箱首頁(yè)菜單欄元素
?5?homePage=id->_mail_tabitem_0_3text
?6?mailList=id->_mail_tabitem_1_4text
?7?applicationCenter=id->_mail_tabitem_2_5text
?8?inBox=id->_mail_tabitem_3_6text
?9?[LoginPageElements];126郵箱登錄頁(yè)面的元素
10?frame=xpath->//div[@id="loginDiv"]/iframe
11?username=xpath->//input[@name="email"]
12?password=xpath->//input[@name="password"]
13?loginBtn=xpath->//a[@id="dologin"]
14?ferrorHead=xpath->//div[@class="ferrorhead"]
15?[ContactPageElements];126郵箱添加聯(lián)系人頁(yè)面元素
16?new_contact=xpath->//span[text()="新建聯(lián)系人"]
17?name=id->input_N
18?mail=xpath->//div[@id="iaddress_MAIL_wrap"]//input[@class="nui-ipt-input"]
19?star=xpath->//span[@class="nui-chk-text"]/preceding-sibling::span/b
20?phone=xpath->//div[@id='iaddress_TEL_wrap']//input[@class='nui-ipt-input']
21?comment=id->input_DETAIL
22?commit=xpath->//span[text()='確?定']
23?tooltip=xpath->//span[text()='請(qǐng)正確填寫郵件地址。']
24?[SendMailPageElements];126郵箱發(fā)送郵件頁(yè)面元素
25?writeMail=xpath->//div[@id='dvNavContainer']//span[text()='寫?信']
26?addressee=xpath->//input[@aria-label='收件人地址輸入框,請(qǐng)輸入郵件地址,多人時(shí)地址請(qǐng)以分號(hào)隔開(kāi)']
27?subject=xpath->//input[contains(@id,?'_subjectInput')]
28?iframe=xpath->//iframe[@class="APP-editor-iframe"]
29?text=xpath->/html/body
30?sendBtn=xpath->//header//span[text()='發(fā)送']
31?expect=xpath->//h1[contains(@id,'_succInfo')]
32?uploadAttachment=xpath->//div[@title="點(diǎn)擊添加附件"]
33?delete=xpath->//a[text()='刪除']

新建excel文件,分3個(gè)sheet,分別為:login,contact,mail #每個(gè)sheet中數(shù)據(jù)可自行填寫,驅(qū)動(dòng)測(cè)試用例執(zhí)行不同的數(shù)據(jù)進(jìn)行測(cè)試
login

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

contact

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

mail

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

數(shù)據(jù),UI對(duì)象庫(kù),解析方法都已經(jīng)有了,接下來(lái)通過(guò)PageObject模式設(shè)計(jì)編寫每個(gè)頁(yè)面的操作及封裝126郵箱的功能,以便后續(xù)設(shè)計(jì)用例調(diào)用
BasePage.py-webdriver二次封裝

?1?"""
??2?------------------------------------
??3?@Time?:?2019/4/20?8:45
??4?@Auth?:?linux超
??5?@File?:?BasePage.py
??6?@IDE??:?PyCharm
??7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
??8?------------------------------------
??9?"""
?10?import?time
?11?from?selenium.webdriver.support?import?expected_conditions?as?EC
?12?from?selenium.webdriver.support.wait?import?WebDriverWait?as?wd
?13?from?selenium.webdriver.common.by?import?By
?14?from?selenium.common.exceptions?import?NoSuchWindowException,?TimeoutException,?\
?15?????NoAlertPresentException,?NoSuchFrameException
?16?from?selenium?import?webdriver
?17?
?18?from?util.clipboard?import?ClipBoard
?19?from?util.keyboard?import?KeyBoard
?20?from?util.parseConFile?import?ParseConFile
?21?from?util.parseExcelFile?import?ParseExcel
?22?
?23?
?24?class?BasePage(object):
?25?????"""
?26?????結(jié)合顯示等待封裝一些selenium?內(nèi)置方法
?27?????"""
?28?????cf?=?ParseConFile()
?29?????excel?=?ParseExcel()
?30?
?31?????def?__init__(self,?driver,?outTime=30):
?32?????????self.byDic?=?{
?33?????????'id':?By.ID,
?34?????????'name':?By.NAME,
?35?????????'class_name':?By.CLASS_NAME,
?36?????????'xpath':?By.XPATH,
?37?????????'link_text':?By.LINK_TEXT
?38?????????}
?39?????????self.driver?=?driver
?40?????????self.outTime?=?outTime
?41?
?42?????def?findElement(self,?by,?locator):
?43?????????"""
?44?????????find?alone?element
?45?????????:param?by:?eg:?id,?name,?xpath,?css.....
?46?????????:param?locator:?id,?name,?xpath?for?str
?47?????????:return:?element?object
?48?????????"""
?49?????????try:
?50?????????????print('[Info:Starting?find?the?element?"{}"?by?"{}"!]'.format(locator,?by))
?51?????????????element?=?wd(self.driver,?self.outTime).until(lambda?x?:?x.find_element(by,?locator))
?52?????????except?TimeoutException?as?t:
?53?????????????print('error:?found?"{}"?timeout!'.format(locator),?t)
?54?????????except?NoSuchWindowException?as?e:
?55?????????????print('error:?no?such?"{}"'.format(locator),?e)
?56?????????except?Exception?as?e:
?57?????????????raise?e
?58?????????else:
?59?????????????#?print('[Info:Had?found?the?element?"{}"?by?"{}"!]'.format(locator,?by))
?60?????????????return?element
?61?
?62?????def?findElements(self,?by,?locator):
?63?????????"""
?64?????????find?group?elements
?65?????????:param?by:?eg:?id,?name,?xpath,?css.....
?66?????????:param?locator:?eg:?id,?name,?xpath?for?str
?67?????????:return:?elements?object
?68?????????"""
?69?????????try:
?70?????????????print('[Info:start?find?the?elements?"{}"?by?"{}"!]'.format(locator,?by))
?71?????????????elements?=?wd(self.driver,?self.outTime).until(lambda?x?:?x.find_element(by,?locator))
?72?????????except?TimeoutException?as?t:
?73?????????????print(t)
?74?????????except?NoSuchWindowException?as?e:
?75?????????????print(e)
?76?????????except?Exception?as?e:
?77?????????????raise?e
?78?????????else:
?79?????????????#?print('[Info:Had?found?the?elements?"{}"?by?"{}"!]'.format(locator,?by))
?80?????????????return?elements
?81?
?82?????def?isElementExsit(self,?by,?locator):
?83?????????"""
?84?????????assert?element?if?exist
?85?????????:param?by:?eg:?id,?name,?xpath,?css.....
?86?????????:param?locator:?eg:?id,?name,?xpath?for?str
?87?????????:return:?if?element?return?True?else?return?false
?88?????????"""
?89?????????if?by.lower()?in?self.byDic:
?90?????????????try:
?91?????????????????wd(self.driver,?self.outTime).\
?92?????????????????????until(EC.visibility_of_element_located((self.byDic[by],?locator)))
?93?????????????except?TimeoutException:
?94?????????????????print('Error:?element?"{}"?time?out!'.format(locator))
?95?????????????????return?False
?96?????????????except?NoSuchWindowException:
?97?????????????????print('Error:?element?"{}"?not?exsit!'.format(locator))
?98?????????????????return?False
?99?????????????return?True
100?????????else:
101?????????????print('the?"{}"?error!'.format(by))
102?
103?????def?isClick(self,?by,?locator):
104?????????"""判斷是否可點(diǎn)擊,返回元素對(duì)象"""
105?????????if?by.lower()?in?self.byDic:
106?????????????try:
107?????????????????element?=?wd(self.driver,?self.outTime).\
108?????????????????????until(EC.element_to_be_clickable((self.byDic[by],?locator)))
109?????????????except?Exception:
110?????????????????return?False
111?????????????return?element
112?????????else:
113?????????????print('the?"{}"?error!'.format(by))
114?
115?????def?isAlertAndSwitchToIt(self):
116?????????"""
117?????????assert?alert?if?exsit
118?????????:return:?alert?obj
119?????????"""
120?????????try:
121?????????????re?=?wd(self.driver,?self.outTime).until(EC.alert_is_present())
122?????????except?NoAlertPresentException:
123?????????????return?False
124?????????except?Exception:
125?????????????return?False
126?????????return?re
127?
128?????def?switchToFrame(self,?by,?locator):
129?????????"""判斷frame是否存在,存在就跳到frame"""
130?????????print('info:switching?to?iframe?"{}"'.format(locator))
131?????????if?by.lower()?in?self.byDic:
132?????????????try:
133?????????????????wd(self.driver,?self.outTime).\
134?????????????????????until(EC.frame_to_be_available_and_switch_to_it((self.byDic[by],?locator)))
135?????????????except?TimeoutException?as?t:
136?????????????????print('error: found "{}" timeout!'.format(locator),?t)
137?????????????except?NoSuchFrameException?as?e:
138?????????????????print('error:?no?such?"{}"'.format(locator),?e)
139?????????????except?Exception?as?e:
140?????????????????raise?e
141?????????else:
142?????????????print('the?"{}"?error!'.format(by))
143?
144?????def?switchToDefaultFrame(self):
145?????????"""返回默認(rèn)的frame"""
146?????????print('info:switch?back?to?default?iframe')
147?????????try:
148?????????????self.driver.switch_to.default_content()
149?????????except?Exception?as?e:
150?????????????print(e)
151?
152?????def?getAlertText(self):
153?????????"""獲取alert的提示信息"""
154?????????if?self.isAlertAndSwitchToIt():
155?????????????alert?=?self.isAlertAndSwitchToIt()
156?????????????return?alert.text
157?????????else:
158?????????????return?None
159?
160?????def?getElementText(self,?by,?locator,?name=None):
161?????????"""獲取某一個(gè)元素的text信息"""
162?????????try:
163?????????????element?=?self.findElement(by,?locator)
164?????????????if?name:
165?????????????????return?element.get_attribute(name)
166?????????????else:
167?????????????????return?element.text
168?????????except:
169?????????????print('get?"{}"?text?failed?return?None'.format(locator))
170?????????????return?None
171?
172?????def?loadUrl(self,?url):
173?????????"""加載url"""
174?????????print('info:?string?upload?url?"{}"'.format(url))
175?????????self.driver.get(url)
176?
177?????def?getSource(self):
178?????????"""獲取頁(yè)面源碼"""
179?????????return?self.driver.page_source
180?
181?????def?sendKeys(self,?by,?locator,?value=''):
182?????????"""寫數(shù)據(jù)"""
183?????????print('info:input?"{}"'.format(value))
184?????????try:
185?????????????element?=?self.findElement(by,?locator)
186?????????????element.send_keys(value)
187?????????except?AttributeError?as?e:
188?????????????print(e)
189?
190?????def?clear(self,?by,?locator):
191?????????"""清理數(shù)據(jù)"""
192?????????print('info:clearing?value')
193?????????try:
194?????????????element?=?self.findElement(by,?locator)
195?????????????element.clear()
196?????????except?AttributeError?as?e:
197?????????????print(e)
198?
199?????def?click(self,?by,?locator):
200?????????"""點(diǎn)擊某個(gè)元素"""
201?????????print('info:click?"{}"'.format(locator))
202?????????element?=?self.isClick(by,?locator)
203?????????if?element:
204?????????????element.click()
205?????????else:
206?????????????print('the?"{}"?unclickable!')
207?
208?????def?sleep(self,?num=0):
209?????????"""強(qiáng)制等待"""
210?????????print('info:sleep?"{}"?minutes'.format(num))
211?????????time.sleep(num)
212?
213?????def?ctrlV(self,?value):
214?????????"""ctrl?+?V?粘貼"""
215?????????print('info:pasting?"{}"'.format(value))
216?????????ClipBoard.setText(value)
217?????????self.sleep(3)
218?????????KeyBoard.twoKeys('ctrl',?'v')
219?
220?????def?enterKey(self):
221?????????"""enter?回車鍵"""
222?????????print('info:keydown?enter')
223?????????KeyBoard.oneKey('enter')
224?
225?????def?waitElementtobelocated(self,?by,?locator):
226?????????"""顯示等待某個(gè)元素出現(xiàn),且可見(jiàn)"""
227?????????print('info:waiting?"{}"?to?be?located'.format(locator))
228?????????try:
229?????????????wd(self.driver,?self.outTime).until(EC.visibility_of_element_located((self.byDic[by],?locator)))
230?????????except?TimeoutException?as?t:
231?????????????print('error: found "{}" timeout!'.format(locator),?t)
232?????????except?NoSuchWindowException?as?e:
233?????????????print('error:?no?such?"{}"'.format(locator),?e)
234?????????except?Exception?as?e:
235?????????????raise?e
236?
237?????def?assertValueInSource(self,?value):
238?????????"""斷言某個(gè)關(guān)鍵字是否存在頁(yè)面源碼中"""
239?????????print('info:assert?"{}"?in?page?source'.format(value))
240?????????source?=?self.getSource()
241?????????assert?value?in?source,?'關(guān)鍵字"{}"不存在源碼中!'.format(value)
242?
243?????def?assertStringContainsValue(self,?String,?value):
244?????????"""斷言某段字符串包含另一個(gè)字符串"""
245?????????print('info:assert?"{}"?contains?"{}"'.format(String,?value))
246?????????assert?value?in?String,?'"{}"不包含"{}"!'.format(String,?value)
247?
248?
249?????@staticmethod
250?????def?getSheet(sheetName):
251?????????"""獲取某個(gè)sheet頁(yè)的對(duì)象"""
252?????????sheet?=?BasePage.excel.getSheetByName(sheetName)
253?????????return?sheet
254?
255?
256?if?__name__?==?"__main__":
257?????driver?=?webdriver.Firefox()
258?????frame?=?('xpath',?'//div[@id="loginDiv"]/ifram')
259?????wait?=?BasePage(driver)
260?????driver.get('https://mail.126.com/')
261?????wait.switchToFrame(*frame)
262?????username?=?wait.findElement('xpath',?'//input[@name="email"]')
263?????username.send_keys('賬號(hào)')
264?????if?wait.isElementExsit('xpath',?'//input[@name="password"]'):
265?????????wait.findElement('xpath',?'//input[@name="password"]').send_keys('xiaochao11520')
266?????wait.click('xpath',?'//a[@id="dologin"]')

HomePage.py-郵箱首頁(yè)選擇菜單

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?12:28
?4?@Auth?:?linux超
?5?@File?:?HomePage.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?from?Page.BasePage?import?BasePage
11?
12?
13?class?HomePage(BasePage):
14?????#?配置文件讀取元素
15?????homePage?=?BasePage.cf.getLocatorsOrAccount('HomePageElements',?'homePage')
16?????mailList?=?BasePage.cf.getLocatorsOrAccount('HomePageElements',?'mailList')
17?????applicationCenter?=?BasePage.cf.getLocatorsOrAccount('HomePageElements',?'applicationCenter')
18?????inBox?=?BasePage.cf.getLocatorsOrAccount('HomePageElements',?'inBox')
19?????'''首頁(yè)菜單選項(xiàng)'''
20?????def?selectMenu(self,?Menu='mailList'):
21?????????"""郵箱首頁(yè)選擇菜單"""
22?????????if?Menu?==?'mailList':
23?????????????self.click(*HomePage.mailList)
24?????????elif?Menu?==?'homePage':
25?????????????self.click(*HomePage.homePage)
26?????????elif?Menu?==?'applicationCenter':
27?????????????self.click(*HomePage.applicationCenter)
28?????????elif?Menu?==?'inBox':
29?????????????self.click(*HomePage.inBox)
30?????????else:
31?????????????raise?ValueError('''
32?????????????菜單選擇錯(cuò)誤!
33?????????????homePage->首頁(yè)
34?????????????mailList->通訊錄
35?????????????applicationCenter->應(yīng)用中心
36?????????????inBox->收件箱''')
37?
38?if?__name__=='__main__':
39?????from?selenium?import?webdriver
40?????from?Page.PageObject.LoginPage?import?LoginPage
41?????driver?=?webdriver.Firefox()
42?????login?=?LoginPage(driver)
43?????login.login('賬號(hào)',?'xiaochao11520')
44?
45?????home?=?HomePage(driver)
46?????home.selectMenu()

LoginPage.py-封裝登錄功能

1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?12:28
?4?@Auth?:?linux超
?5?@File?:?LoginPage.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?from?Page.BasePage?import?BasePage
11?
12?
13?class?LoginPage(BasePage):
14?
15?????#?配置文件讀取元素
16?????frame?=?BasePage.cf.getLocatorsOrAccount('LoginPageElements',?'frame')
17?????username?=?BasePage.cf.getLocatorsOrAccount('LoginPageElements',?'username')
18?????password?=?BasePage.cf.getLocatorsOrAccount('LoginPageElements',?'password')
19?????loginBtn?=?BasePage.cf.getLocatorsOrAccount('LoginPageElements',?'loginBtn')
20?????ferrorHead?=?BasePage.cf.getLocatorsOrAccount('LoginPageElements',?'ferrorHead')??#?登錄失敗提示
21?
22?????def?login(self,?userName,?passWord):
23?????????'''登錄'''
24?????????print('-------staring?login-------')
25?????????self.loadUrl('https://mail.126.com')
26?????????self.switchToFrame(*LoginPage.frame)
27?????????self.clear(*LoginPage.username)
28?????????self.sendKeys(*LoginPage.username,?userName)
29?????????self.clear(*LoginPage.password)
30?????????self.sendKeys(*LoginPage.password,?passWord)
31?????????self.click(*LoginPage.loginBtn)
32?????????self.switchToDefaultFrame()
33?????????print('---------end?login---------')
34?
35?????#?add?at?2019/04/19
36?????def?assertTextEqString(self,?expected,?name?=?None):
37?????????'''斷言提示信息是否與期望的值相等'''
38?????????self.switchToFrame(*LoginPage.frame)
39?????????text?=?self.getElementText(*LoginPage.ferrorHead,?name)
40?????????self.switchToDefaultFrame()
41?????????print('info:?assert?"{}"?==?"{}"'.format(text,?expected))
42?????????assert?text?==?expected,?'{}?!=?{}'.format(text,?expected)
43?
44?if?__name__=="__main__":
45?????from?selenium?import?webdriver
46?????driver?=?webdriver.Firefox()
47?????login?=?LoginPage(driver,?30)
48?????login.login('lin',?'')
49?????login.assertTextEqString('請(qǐng)輸入密碼')

ContactPage.py-封裝添加聯(lián)系人功能

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?12:29
?4?@Auth?:?linux超
?5?@File?:?ContactPage.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?from?Page.BasePage?import?BasePage
11?
12?
13?class?ContactPage(BasePage):
14?????#?配置文件讀取元素
15?????new_contact?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'new_contact')
16?????name?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'name')
17?????mail?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'mail')
18?????star?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'star')
19?????phone?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'phone')
20?????comment?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'comment')
21?????commit?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'commit')
22?????errortip?=?BasePage.cf.getLocatorsOrAccount('ContactPageElements',?'tooltip')??#?錯(cuò)誤提示
23?
24?????def?newContact(self,?Name,?Mail,?Star,?Phone,?Comment):
25?????????"""添加聯(lián)系人"""
26?????????print('--------string?add?contact--------')
27?????????self.click(*ContactPage.new_contact)
28?????????self.sendKeys(*ContactPage.name,?Name)
29?????????self.sendKeys(*ContactPage.mail,?Mail)
30?????????if?Star?==?'1':
31?????????????self.click(*ContactPage.star)
32?????????self.sendKeys(*ContactPage.phone,?Phone)
33?????????self.sendKeys(*ContactPage.comment,?Comment)
34?????????self.click(*ContactPage.commit)
35?????????print('--------end?add?contact--------')
36?
37?????def?assertErrorTip(self,?excepted):
38?????????"""斷言聯(lián)系人添加失敗時(shí)是否有提示信息"""
39?????????text?=?self.getElementText(*ContactPage.errortip)
40?????????print('info:?assert?"{}"=="{}"'.format(text,?excepted))
41?????????assert?text?==?excepted
42?
43?if?__name__?==?'__main__':
44?????from?selenium?import?webdriver
45?????from?Page.PageObject.LoginPage?import?LoginPage
46?????from?Page.PageObject.HomePage?import?HomePage
47?????driver?=?webdriver.Firefox()
48?????home?=?HomePage(driver)
49?????login?=?LoginPage(driver)
50?????contact?=?ContactPage(driver)
51?
52?????login.login('賬號(hào)',?'xiaochao11520')
53?????home.selectMenu()
54?????contact.newContact('281754041@qq.com')

SendMailPage.py-封裝發(fā)送郵件功能

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?9:16
?4?@Auth?:?linux超
?5?@File?:?SendMailPage.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?from?Page.BasePage?import?BasePage
11?
12?
13?class?SendMailPage(BasePage):
14?????#?配置文件讀取元素
15?????writeMail?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'writeMail')
16?????addressee?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'addressee')
17?????subject?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'subject')
18?????iframe?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'iframe')
19?????text?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'text')
20?????sendBtn?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'sendBtn')
21?????expect?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'expect')
22?????uploadAttachment?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'uploadAttachment')
23?????delete?=?BasePage.cf.getLocatorsOrAccount('SendMailPageElements',?'delete')
24?
25?????def?sendMail(self,?Address,?Subject,?Text,?PFA=''):
26?????????"""發(fā)送郵件功能"""
27?????????print('------------string?send?mail---------------------')
28?????????self.click(*SendMailPage.writeMail)
29?????????self.sendKeys(*SendMailPage.addressee,?Address)
30?????????self.sendKeys(*SendMailPage.subject,?Subject)
31?????????self.switchToFrame(*SendMailPage.iframe)
32?????????self.sendKeys(*SendMailPage.text,?Text)
33?????????self.switchToDefaultFrame()
34?????????if?PFA:
35?????????????self.click(*SendMailPage.uploadAttachment)
36?????????????self.ctrlV(PFA)
37?????????????self.enterKey()
38?????????????self.waitElementtobelocated(*SendMailPage.delete)
39?????????self.click(*SendMailPage.sendBtn)
40?????????print('------------end?send?mail---------------------')
41?
42?if?__name__=='__main__':
43?????from?Page.PageObject.LoginPage?import?LoginPage
44?????from?selenium?import?webdriver
45?????driver?=?webdriver.Firefox()
46?
47?????login?=?LoginPage(driver)
48?????login.login('賬號(hào)',?'xiaochao11520')
49?????sendMail?=?SendMailPage(driver)
50?????sendMail.sendMail('281754043@qq.com',?'pytest',?'pytest實(shí)戰(zhàn)實(shí)例',?1,?'D:\KeyWordDriverTestFrameWork\geckodriver.log')

所有的準(zhǔn)備工作都已經(jīng)做好了,還有一個(gè)問(wèn)題,我們的添加聯(lián)系人和發(fā)送郵件應(yīng)該是否應(yīng)該在已經(jīng)登錄的前提下測(cè)試呢?答案是肯定的。所以我們?cè)谟美夸浵滦陆╟onftest.py文件并調(diào)用登錄功能(為什么這么做,不明白的小伙伴可以去看一下我之前的文章,關(guān)于conftest.py的原理)
conftest.py-同用例目錄下,調(diào)用登錄功能

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?15:10
?4?@Auth?:?linux超
?5?@File?:?conftest.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?pytest
11?from?Page.PageObject.LoginPage?import?LoginPage
12?
13?
14?#?從配置文件中獲取正確的用戶名和密碼
15?userName?=?LoginPage.cf.getLocatorsOrAccount('126LoginAccount',?'username')
16?passWord?=?LoginPage.cf.getLocatorsOrAccount('126LoginAccount',?'password')
17?@pytest.fixture(scope='function')
18?def?login(driver):
19?????'''除登錄用例,每一個(gè)用例的前置條件'''
20?????print('------------staring?login------------')
21?????loginFunc?=?LoginPage(driver,?30)
22?????loginFunc.login(userName,?passWord)
23?????yield
24?????print('------------end?login------------')
25?????driver.delete_all_cookies()

ok,開(kāi)始編寫測(cè)試用例啦
test_loginCase.py-登錄功能測(cè)試

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?14:10
?4?@Auth?:?linux超
?5?@File?:?test_loginCase.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?pytest
11?from?Page.PageObject.LoginPage?import?LoginPage
12?
13?
14?@pytest.mark.loginTest
15?class?TestLogin(object):
16?
17?????#?測(cè)試數(shù)據(jù)
18?????loginSheet?=?LoginPage.getSheet('login')
19?????data?=?LoginPage.excel.getAllValuesOfSheet(loginSheet)
20?
21?????#?正確的帳號(hào)和密碼
22?????userName?=?LoginPage.cf.getLocatorsOrAccount('126LoginAccount',?'username')
23?????passWord?=?LoginPage.cf.getLocatorsOrAccount('126LoginAccount',?'password')
24?
25?????@pytest.fixture()
26?????def?teardown_func(self,?driver):
27?????????"""
28?????????執(zhí)行每個(gè)用例之后要清除一下cookie,
29?????????否則你第一個(gè)賬號(hào)登錄之后,重新加載網(wǎng)址還是登錄狀態(tài),無(wú)法測(cè)試后面的賬號(hào)
30?????????"""
31?????????yield
32?????????driver.delete_all_cookies()
33?
34?????@pytest.mark.parametrize('username,?password,?expect',?data)
35?????def?test_login(self,?teardown_func,?driver,?username,?password,?expect):
36?????????"""測(cè)試登錄"""
37?????????login?=?LoginPage(driver,?30)
38?????????login.login(username,?password)
39?????????login.sleep(5)
40?????????#?增加登錄失敗時(shí),?對(duì)提示信息的驗(yàn)證
41?????????if?username?==?TestLogin.userName?and?password?==?TestLogin.passWord:
42?????????????login.assertValueInSource(expect)
43?????????elif?username?==?'':
44?????????????login.assertTextEqString(expect)
45?????????elif?username?!=?''?and?password?==?'':
46?????????????login.assertTextEqString(expect)
47?????????elif?username?==?''?and?password?==?'':
48?????????????login.assertTextEqString(expect)
49?????????else:
50?????????????login.assertTextEqString(expect)
51?
52?
53?if?__name__?==?"__main__":
54?????pytest.main(['-v',?'test_loginCase.py'])

test_contactCase.py-添加聯(lián)系人功能測(cè)試

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?16:15
?4?@Auth?:?linux超
?5?@File?:?test_contactCase.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?re
11?import?pytest
12?from?Page.PageObject.HomePage?import?HomePage
13?from?Page.PageObject.ContactPage?import?ContactPage
14?
15?
16?@pytest.mark.conatctTest
17?class?TestAddContact(object):
18?
19?????#?測(cè)試數(shù)據(jù)
20?????contactSheet?=?ContactPage.getSheet('contact')
21?????data?=?ContactPage.excel.getAllValuesOfSheet(contactSheet)
22?
23?????@pytest.mark.newcontact
24?????@pytest.mark.parametrize('Name,?Mail,?Star,?Phone,?Comment,?expect',?data)
25?????def?test_NewContact(self,?driver,?login,?Name,?Mail,?Star,?Phone,?Comment,?expect):
26?????????"""測(cè)試添加聯(lián)系人"""
27?????????home_page?=?HomePage(driver)
28?????????contact_page?=?ContactPage(driver)
29?????????home_page.selectMenu()
30?????????contact_page.newContact(Name,?Mail,?Star,?Phone,?Comment)
31?????????home_page.sleep(5)
32?????????#?校驗(yàn)錯(cuò)誤的郵箱是否提示信息正確
33?????????if?re.match(r'^.{1,}@[0-9a-zA-Z]{1,13}\..*$',?Mail):
34?????????????contact_page.assertValueInSource(expect)
35?????????else:
36?????????????contact_page.assertErrorTip(expect)
37?
38?if?__name__?==?'__main__':
39?????pytest.main(['-v',?'test_contactCase.py'])

test_sendMailCase.py-發(fā)送郵件功能測(cè)試

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?10:04
?4?@Auth?:?linux超
?5?@File?:?test_sendMailCase.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?pytest
11?from?Page.PageObject.SendMailPage?import?SendMailPage
12?
13?@pytest.mark.sendMailTest
14?class?TestSendMail(object):
15?
16?????sendMailSheet?=?SendMailPage.getSheet('mail')
17?????data?=?SendMailPage.excel.getAllValuesOfSheet(sendMailSheet)
18?
19?????@pytest.mark.sendmail
20?????@pytest.mark.parametrize('Address,?Subject,?Text,?PFA',?data)
21?????def?test_sendMail(self,?driver,?login,?Address,?Subject,?Text,PFA):
22?????????"""測(cè)試發(fā)送郵件,包括帶附件的郵件"""
23?????????send_mail?=?SendMailPage(driver)
24?????????send_mail.sendMail(Address,?Subject,?Text,?PFA)
25?????????send_mail.sleep(5)
26?????????assert?send_mail.isElementExsit(*SendMailPage.expect)
27?
28?if?__name__=='__main__':
29?????pytest.main(['-v',?'test_sendMailCase.py'])

問(wèn)題

用例已經(jīng)寫完了,有兩個(gè)問(wèn)題

1.有沒(méi)有發(fā)現(xiàn)我們的報(bào)告怎么生成的?也沒(méi)有失敗用例截圖?

2.我們貌似并沒(méi)有編寫驅(qū)動(dòng)瀏覽器的代碼?

現(xiàn)在我們來(lái)解決這個(gè)兩個(gè)問(wèn)題

根據(jù)pytest的conftest.py文件的原理,我們可以把驅(qū)動(dòng)瀏覽器的代碼寫在一個(gè)全局的conftest.py文件里面。報(bào)告生成其實(shí)是通過(guò)命令 pytest --html=‘report.html’ --self-contained-html生成的,但是這樣的報(bào)告對(duì)用例的描述不是很清晰,且沒(méi)有對(duì)失敗用例截圖,也不方便我們分析項(xiàng)目的缺陷,我們也可以填寫代碼放到這個(gè)文件里面
conftest.py-全局conftest.py文件

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/12?14:10
?4?@Auth?:?linux超
?5?@File?:?conftest.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?pytest
11?from?selenium?import?webdriver
12?from?py._xmlgen?import?html
13?
14?_driver?=?None
15?#?測(cè)試失敗時(shí)添加截圖和測(cè)試用例描述(用例的注釋信息)
16?
17?@pytest.mark.hookwrapper
18?def?pytest_runtest_makereport(item):
19?????"""
20?????當(dāng)測(cè)試失敗的時(shí)候,自動(dòng)截圖,展示到html報(bào)告中
21?????:param?item:
22?????"""
23?????pytest_html?=?item.config.pluginmanager.getplugin('html')
24?????outcome?=?yield
25?????report?=?outcome.get_result()
26?????extra?=?getattr(report,?'extra',?[])
27?
28?????if?report.when?==?'call'?or?report.when?==?"setup":
29?????????xfail?=?hasattr(report,?'wasxfail')
30?????????if?(report.skipped?and?xfail)?or?(report.failed?and?not?xfail):
31?????????????file_name?=?report.nodeid.replace("::",?"_")+".png"
32?????????????screen_img?=?_capture_screenshot()
33?????????????if?file_name:
34?????????????????html?=?'<div><img?src="data:image/png;base64,%s"?alt="screenshot"?style="width:600px;height:300px;"?'?\
35????????????????????????'onclick="window.open(this.src)"?align="right"/></div>'?%?screen_img
36?????????????????extra.append(pytest_html.extras.html(html))
37?????????report.extra?=?extra
38?????????report.description?=?str(item.function.__doc__)
39?????????report.nodeid?=?report.nodeid.encode("utf-8").decode("unicode_escape")
40?
41?
42?@pytest.mark.optionalhook
43?def?pytest_html_results_table_header(cells):
44?????cells.insert(1,?html.th('Description'))
45?????cells.insert(2,?html.th('Test_nodeid'))
46?????cells.pop(2)
47?
48?
49?@pytest.mark.optionalhook
50?def?pytest_html_results_table_row(report,?cells):
51?????cells.insert(1,?html.td(report.description))
52?????cells.insert(2,?html.td(report.nodeid))
53?????cells.pop(2)
54?
55?
56?def?_capture_screenshot():
57?????"""
58?????截圖保存為base64
59?????:return:
60?????"""
61?????return?_driver.get_screenshot_as_base64()
62?#?這里我設(shè)置的級(jí)別是模塊級(jí)別,也就是每個(gè)測(cè)試文件運(yùn)行一次
63?#?可以設(shè)置為session,全部用例執(zhí)行一次,但是針對(duì)126郵箱的話
64?#?登錄次數(shù)太多會(huì)叫你驗(yàn)證,如果驗(yàn)證就沒(méi)法執(zhí)行用例了,我沒(méi)有對(duì)驗(yàn)證處理(處理比較復(fù)雜)
65?
66?
67?@pytest.fixture(scope='module')
68?def?driver():
69?????global?_driver
70?????print('------------open?browser------------')
71?????_driver?=?webdriver.Firefox()
72?
73?????yield?_driver
74?????print('------------close?browser------------')
75?????_driver.quit()

最后呢,為了減小項(xiàng)目維護(hù)成本,我們把一些全局的配置項(xiàng),放到我們的功能配置文件中共全局使用,包括運(yùn)行用例的一些命令字符串,可以自行修改
conf.py-全局配置文件

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/20?16:50
?4?@Auth?:?linux超
?5?@File?:?conf.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?from?datetime?import?datetime
11?import?os
12?#?項(xiàng)目根目錄
13?projectDir?=?os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
14?#?報(bào)告目錄
15?reportDir?=?os.path.join(projectDir,?'report')
16?#?ui對(duì)象庫(kù)config.ini文件所在目錄
17?configDir?=?os.path.join(projectDir,?'config',?'config.ini')
18?#?測(cè)試數(shù)據(jù)所在目錄
19?excelPath?=?os.path.join(projectDir,?'data',?'tcData.xlsx')
20?#?當(dāng)前時(shí)間
21?currentTime?=?datetime.now().strftime('%H_%M_%S')
22?
23?#?郵件配置信息
24?#?郵件服務(wù)器
25?smtpServer?=?'smtp.qq.com'
26?#?發(fā)送者
27?fromUser?=?'賬號(hào)@qq.com'
28?#?發(fā)送者密碼
29?fromPassWord?=?'mhxvqpewblldbjhf'
30?#?接收者
31?toUser?=?['賬號(hào)@qq.com']#?可以同時(shí)發(fā)送給多人,追加到列表中
32?#?郵件標(biāo)題
33?subject?=?'xx項(xiàng)目自動(dòng)化測(cè)試報(bào)告'
34?#?郵件正文
35?contents?=?'測(cè)試報(bào)告正文'
36?#?報(bào)告名稱
37?htmlName?=?r'{}\testReport{}.html'.format(reportDir,?currentTime)
38?
39?#?腳本執(zhí)行命令
40?args?=?r'pytest?--html='?+?htmlName+?'?'?+?'--self-contained-html'
41?#?modify?by?linuxchao?at?2019/4/25
42?args_login?=?r'pytest?--html='+?htmlName+?'?'?+?'-m'?+?'?'?+?'loginTest'+?'?--self-contained-html'
43?args_contact?=?r'pytest?--html='+?htmlName+?'?'?+?'-m'?+?'?'?+?'contactTest'+?'?--self-contained-html'
44?args_sendmail?=?r'pytest?--html='+?htmlName+?'?'?+?'-m'?+?'?'?+?'sendMailTest'+?'?--self-contained-html'

運(yùn)行項(xiàng)目

通過(guò)命令運(yùn)行

1.cmd切換到項(xiàng)目的根目錄,執(zhí)行pytest --html=‘report.html’ --self-contained-html命令(此運(yùn)行方式,無(wú)法發(fā)送測(cè)試報(bào)告郵件)

這種方式感覺(jué)有點(diǎn)low,我們換另外一種方式,可以通過(guò)os模塊自動(dòng)執(zhí)行相關(guān)命令,編寫運(yùn)行用例代碼
RunTestCase.py-執(zhí)行用例文件

?1?"""
?2?------------------------------------
?3?@Time?:?2019/4/15?16:14
?4?@Auth?:?linux超
?5?@File?:?RunTestCase.py
?6?@IDE??:?PyCharm
?7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!
?8?------------------------------------
?9?"""
10?import?sys
11?sys.path.append('.')
12?from?config.conf?import?*
13?from?util.sendMailForReprot?import?SendMailWithReport
14?
15?
16?def?main():
17?????#?判斷項(xiàng)目的根目錄是否在sys.path中,沒(méi)有就添加
18?????if?projectDir?not?in?sys.path:
19?????????sys.path.append(projectDir)
20?????#?執(zhí)行用例
21?????os.system(args)
22?????#?發(fā)送郵件
23?????SendMailWithReport.send_mail(
24?????????smtpServer,?fromUser,?fromPassWord,
25?????????toUser,?subject,?contents,
26?????????htmlName)
27?
28?
29?if?__name__?==?'__main__':
30?????main()

我們可以直接執(zhí)行這個(gè)文件執(zhí)行所用的測(cè)試用例了!

其實(shí)我們運(yùn)行用例往往不只是 使用pytest --html=‘report.html’ --self-contained-html 這樣一個(gè)簡(jiǎn)單的命令運(yùn)行,通常會(huì)添加很多的命令選項(xiàng),比如-v,-q,-s等等,那么怎么辦呢?這時(shí)候就用到了pytest.ini配置文件了

只添加了幾個(gè)簡(jiǎn)單的命令選項(xiàng)

pytest.ini-pytest配置文件

1?[pytest]
2?addopts=-vqs
3?testpaths=./TestCases
4?markers=
5?????loginTest:?Run?login?test?cases
6?????contactTest:?Run?add?contact?test?cases
7?????sendMailTest:?Run?send?mail?test?cases

測(cè)試輸出
1.自動(dòng)生成html格式報(bào)告,其中報(bào)告里面附帶用例執(zhí)行日志明細(xì),及用例失敗自動(dòng)截圖(部分報(bào)告展示)

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

2.自動(dòng)發(fā)送測(cè)試郵件給指定用戶

Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全),pytest,selenium,ui,軟件測(cè)試,自動(dòng)化測(cè)試,測(cè)試工具,python

同時(shí),在這我為大家準(zhǔn)備了一份軟件測(cè)試視頻教程(含面試、接口、自動(dòng)化、性能測(cè)試等),就在下方,需要的可以直接去觀看,也可以直接【點(diǎn)擊文末小卡片免費(fèi)領(lǐng)取資料文檔】

7天Python自動(dòng)化測(cè)試速成課,小白也能快速上手(項(xiàng)目實(shí)戰(zhàn))文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-841542.html

到了這里,關(guān)于Pytest+Selenium UI自動(dòng)化測(cè)試實(shí)戰(zhàn)實(shí)例(全)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Python、Pytest、Allure、Selenium和Jenkins實(shí)現(xiàn)自動(dòng)化測(cè)試集成實(shí)例

    Python、Pytest、Allure、Selenium和Jenkins實(shí)現(xiàn)自動(dòng)化測(cè)試集成實(shí)例

    下方查看歷史精選文章 重磅發(fā)布 - 自動(dòng)化框架基礎(chǔ)指南pdfv1.1 大數(shù)據(jù)測(cè)試過(guò)程、策略及挑戰(zhàn) 測(cè)試框架原理,構(gòu)建成功的基石 在自動(dòng)化測(cè)試工作之前,你應(yīng)該知道的10條建議 在自動(dòng)化測(cè)試中,重要的不是工具 本文將介紹如何使用Python、Pytest、Allure、Selenium和Jenkins實(shí)現(xiàn)測(cè)試自動(dòng)

    2024年02月09日
    瀏覽(91)
  • UI自動(dòng)化測(cè)試:Selenium+PO模式+Pytest+Allure整合

    UI自動(dòng)化測(cè)試:Selenium+PO模式+Pytest+Allure整合

    本人目前工作中未涉及到WebUI自動(dòng)化測(cè)試,但為了提升自己的技術(shù),多學(xué)習(xí)一點(diǎn)還是沒(méi)有壞處的,廢話不多說(shuō)了,目前主流的webUI測(cè)試框架應(yīng)該還是selenium,考慮到可維護(hù)性、拓展性、復(fù)用性等,我們采用PO模式去寫我們的腳本,本文檔也主要整合了Selenium+PO模式+Pytest+Allure,下

    2024年02月08日
    瀏覽(506)
  • 【UI自動(dòng)化測(cè)試技術(shù)】自動(dòng)化測(cè)試研究:Python+Selenium+Pytest+Allure,詳解UI自動(dòng)化測(cè)試,學(xué)習(xí)模擬鼠標(biāo)+模擬鍵盤進(jìn)行相關(guān)操作(精)(四)

    1、了解元素交互的常用方法 2、學(xué)習(xí)如何對(duì)多選元素進(jìn)行操作 3、 學(xué)習(xí)模擬鼠標(biāo)進(jìn)行相關(guān)操作 ( 本節(jié)目標(biāo) ) 4、 學(xué)習(xí)模擬鍵盤進(jìn)行相關(guān)操作 ( 本節(jié)目標(biāo) ) 用于向 Web 瀏覽器提供虛擬化設(shè)備輸入操作的低級(jí)接口.除了剛剛講過(guò)的Web元素交互之外, Actions 接口 還提供了對(duì)指定輸

    2024年03月24日
    瀏覽(92)
  • Web UI 自動(dòng)化測(cè)試框架(Pytest+Selenium+Allure+Loguru)

    本框架主要是基于 Python + pytest + selenium + Allure + loguru + 郵件通知/企業(yè)微信通知/釘釘通知 實(shí)現(xiàn)的WEB UI自動(dòng)化框架。 基于PageObject設(shè)計(jì)模式結(jié)合,該平臺(tái)可實(shí)現(xiàn)測(cè)試用例的自動(dòng)化執(zhí)行及自動(dòng)化測(cè)試報(bào)告的生成同時(shí)包括自動(dòng)化測(cè)試執(zhí)行時(shí),用例失敗的截圖操作。 使用webdriver_manag

    2024年02月04日
    瀏覽(363)
  • 2023最全最細(xì)的Selenium+Pytest自動(dòng)化測(cè)試框架實(shí)戰(zhàn)

    2023最全最細(xì)的Selenium+Pytest自動(dòng)化測(cè)試框架實(shí)戰(zhàn)

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 選前言# ? selenium自動(dòng)化+ pytest測(cè)試框架 本章你需要 一定的python基礎(chǔ)——至少明白類與對(duì)象,封裝繼承 一定的selenium基礎(chǔ)——本篇不講selenium,不會(huì)的可以自己去看selenium中文翻譯網(wǎng) 測(cè)試框架簡(jiǎn)介# 測(cè)試框架有什么優(yōu)點(diǎn)呢: 代碼復(fù)用率高,

    2024年02月06日
    瀏覽(27)
  • Web UI 自動(dòng)化測(cè)試框架(Pytest+Selenium+Allure/Pytest-html+Loguru)

    本框架主要是基于 Python + pytest + selenium + Allure + loguru + 郵件通知/企業(yè)微信通知/釘釘通知 實(shí)現(xiàn)的WEB UI自動(dòng)化框架。 基于PageObject設(shè)計(jì)模式結(jié)合,該平臺(tái)可實(shí)現(xiàn)測(cè)試用例的自動(dòng)化執(zhí)行及自動(dòng)化測(cè)試報(bào)告的生成同時(shí)包括自動(dòng)化測(cè)試執(zhí)行時(shí),用例失敗的截圖操作。 使用webdriver_manag

    2024年02月12日
    瀏覽(95)
  • Selenium+Pytest自動(dòng)化測(cè)試框架實(shí)戰(zhàn),還不會(huì)點(diǎn)這里一清二楚,全網(wǎng)最細(xì)教程!

    Selenium+Pytest自動(dòng)化測(cè)試框架實(shí)戰(zhàn),還不會(huì)點(diǎn)這里一清二楚,全網(wǎng)最細(xì)教程!

    在華為工作了10年的大佬出的Web自動(dòng)化測(cè)試教程,華為現(xiàn)用技術(shù)教程!_嗶哩嗶哩_bilibili 在華為工作了10年的大佬出的Web自動(dòng)化測(cè)試教程,華為現(xiàn)用技術(shù)教程!共計(jì)16條視頻,包括:1. 【web自動(dòng)化】主流Web自動(dòng)化測(cè)試技術(shù)對(duì)比、2. 【web自動(dòng)化】Selenium自動(dòng)化測(cè)試環(huán)境一鍵搭建、

    2024年02月02日
    瀏覽(27)
  • selenium+python web自動(dòng)化測(cè)試框架項(xiàng)目實(shí)戰(zhàn)實(shí)例教程

    selenium+python web自動(dòng)化測(cè)試框架項(xiàng)目實(shí)戰(zhàn)實(shí)例教程

    自動(dòng)化測(cè)試對(duì)程序的回歸測(cè)試更方便。 由于回歸測(cè)試的動(dòng)作和用例是完全設(shè)計(jì)好的,測(cè)試期望的結(jié)果也是完全可以預(yù)料的,將回歸測(cè)試自動(dòng)運(yùn)行... 可以運(yùn)行更加繁瑣的測(cè)試 自動(dòng)化測(cè)試的一個(gè)明顯好處就是可以在很短的時(shí)間內(nèi)運(yùn)行更多的測(cè)試。學(xué)習(xí)自動(dòng)化測(cè)試最終目的是應(yīng)用到

    2024年02月06日
    瀏覽(36)
  • Python+Selenium.webdriver實(shí)現(xiàn)WEB端UI自動(dòng)化測(cè)試(實(shí)例腳本)

    Python+Selenium.webdriver實(shí)現(xiàn)WEB端UI自動(dòng)化測(cè)試(實(shí)例腳本)

    ????????本篇記錄基于Python+Selenium.webdriver實(shí)現(xiàn)WEB端UI自動(dòng)化測(cè)試,其中測(cè)試用例使用excel維護(hù)。為了在實(shí)際項(xiàng)目種的擴(kuò)展應(yīng)用,建議學(xué)習(xí)webdriver的元素定位方法,歡迎在評(píng)論區(qū)溝通討論。 該示例選取的是登錄頁(yè)不需要輸入驗(yàn)證碼校驗(yàn)的基礎(chǔ)頁(yè)面(考慮到現(xiàn)在大部分項(xiàng)目都是

    2023年04月08日
    瀏覽(35)
  • 基于Selenium的Web UI自動(dòng)化測(cè)試框架開(kāi)發(fā)實(shí)戰(zhàn)

    基于Selenium的Web UI自動(dòng)化測(cè)試框架開(kāi)發(fā)實(shí)戰(zhàn)

    1、自研自動(dòng)化測(cè)試框架 首先進(jìn)行需求分析。概要設(shè)計(jì)包括以下三大模塊: 公共函數(shù)庫(kù)模塊(包括可復(fù)用函數(shù)庫(kù)、日志管理、報(bào)表管理及發(fā)送郵件管理); 測(cè)試用例倉(cāng)庫(kù)模塊(具體用例的相關(guān)管理); 可視化頁(yè)面管理模塊(單獨(dú)針對(duì)Web頁(yè)面進(jìn)行抽象,封裝頁(yè)面元素和操作方

    2024年01月20日
    瀏覽(115)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包