国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

wordpress主題ruikedu正規(guī)seo關鍵詞排名哪家專業(yè)

wordpress主題ruikedu,正規(guī)seo關鍵詞排名哪家專業(yè),訂貨網(wǎng)站建設,成都seo正規(guī)優(yōu)化🍅 點擊文末小卡片,免費獲取軟件測試全套資料,資料在手,漲薪更快 今天來說說pytest吧,經(jīng)過幾周的時間學習,有收獲也有疑惑,總之最后還是搞個小項目出來證明自己的努力不沒有白費 環(huán)境準備 1 …

🍅?點擊文末小卡片,免費獲取軟件測試全套資料,資料在手,漲薪更快

今天來說說pytest吧,經(jīng)過幾周的時間學習,有收獲也有疑惑,總之最后還是搞個小項目出來證明自己的努力不沒有白費

環(huán)境準備

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

項目簡介

測試地址

https://mail.126.com

測試范圍

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

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

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

項目設計

1.python編程語言設計測試腳本

2.webdriver驅動瀏覽器并操作頁面元素

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

4.采用PageObject設計模式,設計測試業(yè)務流程

5.通過UI對象庫存儲頁面操作元素

6.通過數(shù)據(jù)文件存儲數(shù)據(jù),讀取數(shù)據(jù),參數(shù)化測試用例并驅動測試執(zhí)行

7.通過第三方插件pytest-html生成測試報告

8.通過yagmail第三方庫,編寫發(fā)送報告接口,測試工作完成后自動發(fā)送測試報告

目錄結構

?1?PytestAutoTestFrameWork2?|—|config3?|——|__init__.py4?|——|conf.py5?|——|config.ini6?|—|data7?|——|__init__.py8?|——|tcData.xlsx9?|—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

代碼實現(xiàn)

通過126郵箱測試范圍分析,我們需要通過設計剪切板,模擬鍵盤完成附件上傳操作,因此我們首先來編寫這兩個方法
clipboard.py-操作剪切板

?1?"""2?------------------------------------3?@Time?:?2019/4/15?12:044?@Auth?:?linux超5?@File?:?clipboard.py6?@IDE??:?PyCharm7?@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?????'''設置剪切板內(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?????????'''設置剪切板的內(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:054?@Auth?:?linux超5?@File?:?keyboard.py6?@IDE??:?PyCharm7?@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?????????"""模擬單個按鍵"""
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')

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

?1?"""2?------------------------------------3?@Time?:?2019/4/22?16:124?@Auth?:?linux超5?@File?:?parseExcelFile.py6?@IDE??:?PyCharm7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!8?------------------------------------9?"""10?from?openpyxl?import?load_workbook11?from?config.conf?import?excelPath12?13?14?class?ParseExcel(object):15?16?????def?__init__(self):17?????????self.wk?=?load_workbook(excelPath)18?????????self.excelFile?=?excelPath19?20?????def?getSheetByName(self,?sheetName):21?????????"""獲取sheet對象"""22?????????sheet?=?self.wk[sheetName]23?????????return?sheet24?25?????def?getRowNum(self,?sheet):26?????????"""獲取有效數(shù)據(jù)的最大行號"""27?????????return?sheet.max_row28?29?????def?getColsNum(self,?sheet):30?????????"""獲取有效數(shù)據(jù)的最大列號"""31?????????return?sheet.max_column32?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).value39?????????????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).value50?????????????if?value?is?None:51?????????????????value?=?''52?????????????columnValues.append(value)53?????????return?tuple(columnValues)54?55?????def?getValueOfCell(self,?sheet,?rowNum,?columnNum):56?????????"""獲取某一個單元格的數(shù)據(jù)"""57?????????value?=?sheet.cell(rowNum,?columnNum).value58?????????if?value?is?None:59?????????????value?=?''60?????????return?value61?62?????def?getAllValuesOfSheet(self,?sheet):63?????????"""獲取某一個sheet頁的所有測試數(shù)據(jù),返回一個元祖組成的列表"""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).value71?????????????????if?value?is?None:72?????????????????????value?=?''73?????????????????rowValues.append(value)74?????????????allValues.append(tuple(rowValues))75?????????return?allValues76?77?78?if?__name__?==?'__main__':79?????#?excel?=?ParseExcel()80?????#?sheet?=?excel.getSheetByName('login')81?????#?print('行號:',?excel.getRowNum(sheet))82?????#?print('列號:',?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('行號:',?excel.getRowNum(sheet))97?????print('列號:',?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:544?@Auth?:?linux超5?@File?:?parseConFile.py6?@IDE??:?PyCharm7?@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,返回一個列表"""
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對應的數(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和對應的數(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郵箱正確的登錄賬號和密碼;運行用例時請更換正確的用戶名和密碼2?username=linuxxiaochao3?password=xiaochao115204?[HomePageElements];126郵箱首頁菜單欄元素5?homePage=id->_mail_tabitem_0_3text6?mailList=id->_mail_tabitem_1_4text7?applicationCenter=id->_mail_tabitem_2_5text8?inBox=id->_mail_tabitem_3_6text9?[LoginPageElements];126郵箱登錄頁面的元素
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)系人頁面元素
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()='請正確填寫郵件地址。']
24?[SendMailPageElements];126郵箱發(fā)送郵件頁面元素
25?writeMail=xpath->//div[@id='dvNavContainer']//span[text()='寫?信']
26?addressee=xpath->//input[@aria-label='收件人地址輸入框,請輸入郵件地址,多人時地址請以分號隔開']
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="點擊添加附件"]
33?delete=xpath->//a[text()='刪除']

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

圖片

contact

圖片

mail

圖片

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

?1?"""2?------------------------------------3?@Time?:?2019/4/20?8:454?@Auth?:?linux超5?@File?:?BasePage.py6?@IDE??:?PyCharm7?@Motto:?Real?warriors,dare?to?face?the?bleak?warning,dare?to?face?the?incisive?error!8?------------------------------------9?"""10?import?time11?from?selenium.webdriver.support?import?expected_conditions?as?EC12?from?selenium.webdriver.support.wait?import?WebDriverWait?as?wd13?from?selenium.webdriver.common.by?import?By14?from?selenium.common.exceptions?import?NoSuchWindowException,?TimeoutException,?\15?????NoAlertPresentException,?NoSuchFrameException16?from?selenium?import?webdriver17?18?from?util.clipboard?import?ClipBoard19?from?util.keyboard?import?KeyBoard20?from?util.parseConFile?import?ParseConFile21?from?util.parseExcelFile?import?ParseExcel22?23?24?class?BasePage(object):25?????"""26?????結合顯示等待封裝一些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_TEXT38?????????}39?????????self.driver?=?driver40?????????self.outTime?=?outTime41?42?????def?findElement(self,?by,?locator):43?????????"""44?????????find?alone?element45?????????:param?by:?eg:?id,?name,?xpath,?css.....46?????????:param?locator:?id,?name,?xpath?for?str47?????????:return:?element?object48?????????"""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?e58?????????else:59?????????????#?print('[Info:Had?found?the?element?"{}"?by?"{}"!]'.format(locator,?by))60?????????????return?element61?62?????def?findElements(self,?by,?locator):63?????????"""64?????????find?group?elements65?????????:param?by:?eg:?id,?name,?xpath,?css.....66?????????:param?locator:?eg:?id,?name,?xpath?for?str67?????????:return:?elements?object68?????????"""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?e78?????????else:79?????????????#?print('[Info:Had?found?the?elements?"{}"?by?"{}"!]'.format(locator,?by))80?????????????return?elements81?82?????def?isElementExsit(self,?by,?locator):83?????????"""84?????????assert?element?if?exist85?????????:param?by:?eg:?id,?name,?xpath,?css.....86?????????:param?locator:?eg:?id,?name,?xpath?for?str87?????????:return:?if?element?return?True?else?return?false88?????????"""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?False96?????????????except?NoSuchWindowException:97?????????????????print('Error:?element?"{}"?not?exsit!'.format(locator))98?????????????????return?False99?????????????return?True
100?????????else:
101?????????????print('the?"{}"?error!'.format(by))
102?
103?????def?isClick(self,?by,?locator):
104?????????"""判斷是否可點擊,返回元素對象"""
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?????????"""返回默認的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?????????"""獲取某一個元素的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?????????"""獲取頁面源碼"""
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?????????"""點擊某個元素"""
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?????????"""強制等待"""
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?????????"""顯示等待某個元素出現(xià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?????????"""斷言某個關鍵字是否存在頁面源碼中"""
239?????????print('info:assert?"{}"?in?page?source'.format(value))
240?????????source?=?self.getSource()
241?????????assert?value?in?source,?'關鍵字"{}"不存在源碼中!'.format(value)
242?
243?????def?assertStringContainsValue(self,?String,?value):
244?????????"""斷言某段字符串包含另一個字符串"""
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?????????"""獲取某個sheet頁的對象"""
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('賬號')
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-郵箱首頁選擇菜單

?1?"""2?------------------------------------3?@Time?:?2019/4/20?12:284?@Auth?:?linux超5?@File?:?HomePage.py6?@IDE??:?PyCharm7?@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?????'''首頁菜單選項'''
20?????def?selectMenu(self,?Menu='mailList'):
21?????????"""郵箱首頁選擇菜單"""
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?????????????菜單選擇錯誤!
33?????????????homePage->首頁
34?????????????mailList->通訊錄
35?????????????applicationCenter->應用中心
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('賬號',?'xiaochao11520')
44?
45?????home?=?HomePage(driver)
46?????home.selectMenu()

LoginPage.py-封裝登錄功能

1?"""2?------------------------------------3?@Time?:?2019/4/20?12:284?@Auth?:?linux超5?@File?:?LoginPage.py6?@IDE??:?PyCharm7?@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('請輸入密碼')

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

?1?"""2?------------------------------------3?@Time?:?2019/4/20?12:294?@Auth?:?linux超5?@File?:?ContactPage.py6?@IDE??:?PyCharm7?@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')??#?錯誤提示
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)系人添加失敗時是否有提示信息"""
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('賬號',?'xiaochao11520')
53?????home.selectMenu()
54?????contact.newContact('281754041@qq.com')

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

?1?"""2?------------------------------------3?@Time?:?2019/4/20?9:164?@Auth?:?linux超5?@File?:?SendMailPage.py6?@IDE??:?PyCharm7?@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('賬號',?'xiaochao11520')
49?????sendMail?=?SendMailPage(driver)
50?????sendMail.sendMail('281754043@qq.com',?'pytest',?'pytest實戰(zhàn)實例',?1,?'D:\KeyWordDriverTestFrameWork\geckodriver.log')

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

?1?"""2?------------------------------------3?@Time?:?2019/4/20?15:104?@Auth?:?linux超5?@File?:?conftest.py6?@IDE??:?PyCharm7?@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?????'''除登錄用例,每一個用例的前置條件'''
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,開始編寫測試用例啦
test_loginCase.py-登錄功能測試

?1?"""2?------------------------------------3?@Time?:?2019/4/20?14:104?@Auth?:?linux超5?@File?:?test_loginCase.py6?@IDE??:?PyCharm7?@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?????#?測試數(shù)據(jù)
18?????loginSheet?=?LoginPage.getSheet('login')
19?????data?=?LoginPage.excel.getAllValuesOfSheet(loginSheet)
20?
21?????#?正確的帳號和密碼
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í)行每個用例之后要清除一下cookie,
29?????????否則你第一個賬號登錄之后,重新加載網(wǎng)址還是登錄狀態(tài),無法測試后面的賬號
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?????????"""測試登錄"""
37?????????login?=?LoginPage(driver,?30)
38?????????login.login(username,?password)
39?????????login.sleep(5)
40?????????#?增加登錄失敗時,?對提示信息的驗證
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)系人功能測試

?1?"""2?------------------------------------3?@Time?:?2019/4/20?16:154?@Auth?:?linux超5?@File?:?test_contactCase.py6?@IDE??:?PyCharm7?@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?????#?測試數(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?????????"""測試添加聯(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?????????#?校驗錯誤的郵箱是否提示信息正確
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ā)送郵件功能測試

?1?"""2?------------------------------------3?@Time?:?2019/4/20?10:044?@Auth?:?linux超5?@File?:?test_sendMailCase.py6?@IDE??:?PyCharm7?@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?????????"""測試發(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'])

問題

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

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

2.我們貌似并沒有編寫驅動瀏覽器的代碼?

現(xiàn)在我們來解決這個兩個問題

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

?1?"""2?------------------------------------3?@Time?:?2019/4/12?14:104?@Auth?:?linux超5?@File?:?conftest.py6?@IDE??:?PyCharm7?@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?#?測試失敗時添加截圖和測試用例描述(用例的注釋信息)
16?
17?@pytest.mark.hookwrapper
18?def?pytest_runtest_makereport(item):
19?????"""
20?????當測試失敗的時候,自動截圖,展示到html報告中
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?#?這里我設置的級別是模塊級別,也就是每個測試文件運行一次
63?#?可以設置為session,全部用例執(zhí)行一次,但是針對126郵箱的話
64?#?登錄次數(shù)太多會叫你驗證,如果驗證就沒法執(zhí)行用例了,我沒有對驗證處理(處理比較復雜)
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()

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

?1?"""2?------------------------------------3?@Time?:?2019/4/20?16:504?@Auth?:?linux超5?@File?:?conf.py6?@IDE??:?PyCharm7?@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?#?項目根目錄
13?projectDir?=?os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
14?#?報告目錄
15?reportDir?=?os.path.join(projectDir,?'report')
16?#?ui對象庫config.ini文件所在目錄
17?configDir?=?os.path.join(projectDir,?'config',?'config.ini')
18?#?測試數(shù)據(jù)所在目錄
19?excelPath?=?os.path.join(projectDir,?'data',?'tcData.xlsx')
20?#?當前時間
21?currentTime?=?datetime.now().strftime('%H_%M_%S')
22?
23?#?郵件配置信息
24?#?郵件服務器
25?smtpServer?=?'smtp.qq.com'
26?#?發(fā)送者
27?fromUser?=?'賬號@qq.com'
28?#?發(fā)送者密碼
29?fromPassWord?=?'mhxvqpewblldbjhf'
30?#?接收者
31?toUser?=?['賬號@qq.com']#?可以同時發(fā)送給多人,追加到列表中
32?#?郵件標題
33?subject?=?'xx項目自動化測試報告'
34?#?郵件正文
35?contents?=?'測試報告正文'
36?#?報告名稱
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'

運行項目

通過命令運行

1.cmd切換到項目的根目錄,執(zhí)行pytest --html=‘report.html’ --self-contained-html命令(此運行方式,無法發(fā)送測試報告郵件)

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

?1?"""2?------------------------------------3?@Time?:?2019/4/15?16:144?@Auth?:?linux超5?@File?:?RunTestCase.py6?@IDE??:?PyCharm7?@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?????#?判斷項目的根目錄是否在sys.path中,沒有就添加
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í)行這個文件執(zhí)行所用的測試用例了!

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

只添加了幾個簡單的命令選項

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

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

圖片

圖片

2.自動發(fā)送測試郵件給指定用戶

圖片

最后感謝每一個認真閱讀我文章的人,禮尚往來總是要有的,雖然不是什么很值錢的東西,如果你用得到的話可以直接拿走:

?這些資料,對于做【軟件測試】的朋友來說應該是最全面最完整的備戰(zhàn)倉庫,這個倉庫也陪伴我走過了最艱難的路程,希望也能幫助到你!凡事要趁早,特別是技術行業(yè),一定要提升技術功底。

http://m.aloenet.com.cn/news/37837.html

相關文章:

  • 怎么做app和網(wǎng)站購物最好的營銷策劃公司
  • php網(wǎng)站后臺管理模板推廣排名
  • 什么是網(wǎng)站排名優(yōu)化百度關鍵詞挖掘工具
  • 廣廣東網(wǎng)站建設百度軟件下載中心官方網(wǎng)站
  • 網(wǎng)站建設頁面設計南寧百度seo軟件
  • 姑蘇網(wǎng)站制作國家免費培訓機構
  • 公司要網(wǎng)站建設實時熱搜
  • 梧州市網(wǎng)站建設seo是什么級別
  • 專業(yè)網(wǎng)站構建谷歌優(yōu)化的最佳方案
  • wordpress怎么復制頁面福州網(wǎng)站優(yōu)化公司
  • 南昌網(wǎng)站建設web8848百度一下 官方網(wǎng)
  • 企業(yè)做網(wǎng)站的注意什么百度用戶服務中心官網(wǎng)
  • 常德網(wǎng)站建設案例教程seo培訓一對一
  • 怎么做查詢網(wǎng)站網(wǎng)站排名怎么做上去
  • 做建筑的網(wǎng)站百度百科創(chuàng)建
  • 織夢做的網(wǎng)站怎么樣今日新聞最新事件
  • 減肥養(yǎng)生網(wǎng)站建設自制網(wǎng)站教程
  • 衡水建設投資集團網(wǎng)站萬能軟文范例800字
  • 網(wǎng)站加載頁模板太倉seo網(wǎng)站優(yōu)化軟件
  • 那個網(wǎng)站專做地質基礎信息域名查詢服務器
  • 網(wǎng)站在工信部備案百度seo優(yōu)化招聘
  • 網(wǎng)站為什么不被收錄網(wǎng)絡營銷工具包括
  • 3建設營銷型網(wǎng)站流程圖生成關鍵詞的軟件免費
  • 基于web前端的旅游網(wǎng)站論文自己做一個網(wǎng)站需要多少錢
  • 北京網(wǎng)站制作公司興田德潤可信賴網(wǎng)絡營銷主要學什么
  • 企業(yè)網(wǎng)站建設方案價位企業(yè)網(wǎng)站設計服務
  • 網(wǎng)站制作的困難和解決方案成都推廣系統(tǒng)
  • 蘇州驚天網(wǎng)站制作網(wǎng)想要推廣網(wǎng)頁正式版
  • 山東威海網(wǎng)站開發(fā)關鍵詞推廣排名
  • 做網(wǎng)站被捉域名注冊優(yōu)惠