言
我們在appium做app自動化測試,環境搭建是比較麻煩的。也是很多初學者在學習app自動化之時,花很多時間都難跨越的坎。今天小編就來講講appium如何搭建APP自動化測試環境。喜歡小編的可以給小編點點關注喲。
沒有成功的環境,就沒有辦法繼續后續的使用。
在app自動化測試當中,我們主要是通用電腦端的python代碼,能夠驅使手機端的app去進行操作。比如打開一個app,輸入用戶名和密碼,進入登陸操作。
由于電腦端和手機端是兩個獨立的設備。要實現數據通信,就需要將二者連一起。因此對于真機用戶,需要用USB線連接手機和電腦,并且在開發者選項當中,開啟USB調試模式。
app自動化環境安裝包括以下幾點:
1、安裝node.js
2、安裝appium desktop程序
3、安裝JDK1.8及以上版本
4、安裝安卓開發工具
5、安裝appium python客戶端
6、真機或者模擬器
第一步:安裝nodejs和appium desktop程序
nodejs官網下載地址:https://nodejs.org/en/download/
appium的運行依賴于nodejs,所以要先安裝nodejs。nodejs下載完成之后,windows用戶雙擊安裝完成即可,不需要做額外配置。
appium desktop下載官網:https://github.com/appium/appium-desktop/releases
appium版本更新較快。最新的版本在你的電腦上不一定能運行起來。如果新版本運行不起來,那么建議換其它的版本。
安裝也非常簡單,雙擊exe程序運行即可。
第二步:安裝JDK
JDK要求1.8版本以及以上。參考網上其它文章來安裝jdk。
JDK下載地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
第三步:安裝安卓開發工具
自動化測試當中,會用到一些工具,但不會去開發一個app。所以sdk部分不需要。只需要下載工具部分即可。
安卓sdk下載地址:http://tools.android-studio.org/index.php/sdk
安裝步驟如下:
1)解壓 platform-tools_r28.0.2-windows.zip到本地目錄
2)雙擊SDKManager.exe
3)在SDK Manager界面當中,只勾選:
Tools當中的Android SDK Tools、Android SDK Platform-tools、Android SDK Build-tools
Extras目錄。
其它的一概不勾選。默認選中的請注意取消勾選!!!!
打開SDK Manager,默認會選中安卓sdk,請一定要取消掉。
4)配置環境變量:
4.1 添加ANDROID_HOME環境變量,配置sdk根目錄。
在以上的截圖中,
ANDROID_HOME=D:\android-sdk-windows
4.2 在PATH變量中添加三項內容:
%ANDROID_HOME%\platform-tools
%ANDROID_HOME%\tools
%ANDROID_HOME%\build-tools.0.3
檢測:
進入cmd命令行,輸入adb version
能夠正常顯示adb的版本就okay.
第四步:安裝appium python客戶端
使用python的pip命令,直接在線安裝:
pip install Appium-Python-Client
第五步:安裝模擬器(使用真機的用戶,可以跳過此步驟)
本步驟中,選擇夜神模擬器。
夜神模擬器官方網站下載地址:https://www.yeshen.com/
下載安裝完成之后。桌面會有2個圖標:夜神模擬器、夜神多開器。
夜神模擬器:默認安卓版本為4.4.2
夜神多開器:可以增加安卓5.1模擬器、安卓7.1模擬器。
在啟動模擬器之前,替換模擬器安裝路徑當中的nox_adb.exe
第一步:將%ANDROID_HOME%\platform-tools目錄下的adb.exe拷貝到桌面,更改名稱為nox_adb.exe
第二步:將第一步中的nox_adb拷貝到夜神模擬器安裝目錄下,替換原來的文件。
再去啟動夜神模擬器。然后在cmd命令行當中,輸入命令:adb devices
以上所有步驟安裝完成之后,恭喜你,環境搭建好了!可以開啟app自動化體驗之旅了!!
喜歡的可以點贊關注小編喲!
識Git版本控制
自動化測試代碼反復執行,如果借用持續集成工具會提高測試效率,那么需要我們把自動化測試代碼發布到正式環境中,這時候用Git版本控制工具高效、穩定、便捷。
分布式版本控制
Git可以把代碼倉庫完整地鏡像下來,有完整的歷史記錄,它可以與遠端代碼庫進行交互。
簡史
Git誕生于2005年,速度快,極適合管理大項目。
Git是什么
其他版本控制系統如SVN,是隨時間變化的差異性文件比較,在某時間段某些文件進行更新。
Git是快照流,存儲項目隨時間改變的快照,幾乎大部分操作都只需要訪問本地文件和資源。保證完整性,用哈希Hash,一般只添加數據,不刪除。
Git三種狀態:
已修改:在工作區修改文件,但沒保存到數據庫
已暫存: 在暫存區對已修改的文件做標記,使其包含在下次提交的快照中
已提交:在Git目錄安全地保存數據到本地數據庫
基本Git工作流程:
①工作區修改文件;
②暫存區將下次提交的更改選擇性暫存,修改部分添加到暫存區;
③提交更新,找到暫存區的文件,將快照永久保存在Git目錄。
命令行
所有人都有命令行工具,會命令行則應該會GUI。
安裝Git
本次實踐安裝的最新版2.36.0,官網下載windows版本https://git-scm.com/download/win。
初次運行Git前的配置
1)設置用戶信息,以下命令:
git config --global user.name “”
git config --global user.email “”
如果想給特定項目設置用戶信息,則在該項目目錄下運行無--global的命令。
2)設置文本編輯器,如未配置,Git會使用操作系統自帶的編輯器。
設置notepad++為文本編輯器:
git config --global core.editor “’d:\dev\notepad++\notepad++.exe” -multiInst -notabbar -nosession -noPlugin”
3)檢查配置信息:
git config --list
可逐項檢查,如:
git config username
獲得幫助
git help +Verb,例如git help config。如果不用全面只需快速參考,使用命令git +Verb -h,例如git add -h。
Git基礎
獲取Git倉庫
兩種獲得Git項目倉庫的方式:
①對尚未進行版本控制的本地目錄轉換為Git倉庫;
②從其他服務器克隆一個已存在的Git倉庫。
(1)對已存在目錄中初始化倉庫
如果有一個尚未進行版本控制的項目目錄,想要用Git控制它,那么需要進入該項目目錄中。
在Windows上:
cd c/user/my_project
之后執行:
git init
該命令將創建名為.git的子目錄,這個子目錄含有你做初始化的Git倉庫中所有的必須文件,這些文件是Git倉庫的骨干。這時,我們僅僅是做了一個初始化的操作,你的項目里的文件還沒有被跟蹤。
如圖所示:
圖1
圖2
圖3
如果在一個已存在文件的文件夾(非空文件夾)中進行版本控制,應該開始追蹤這些文件并進行初始提交。
可以通過git add命令指定所需的文件進行追蹤,然后執行git commit:
git add *.c
git add LICENSE
git commit -m ‘initial project version’
如圖所示:
圖4
這樣已經得到了一個存在被追蹤文件與初始提交的Git倉庫。
(2)克隆現有的倉庫
如果想獲得一份已經存在了的Git倉庫的拷貝,比如說,想為某個開源項目貢獻自己的一份力,這時就要用到git clone命令。
如果對其他VCS系統(比如Subversion)很熟悉,請留心以下所使用的命令是“clone”而不是“checkout”。這是Git區別于其他版本控制系統的一個重要特性,Git克隆的是該Git倉庫服務器上的幾乎所有數據,而不是僅僅復制完成你的工作所需要文件。
當你執行git clone命令的時候,默認配置下遠程Git倉庫中的每一個文件的每個版本都將被拉取下來。實際上,如果服務器磁盤壞掉了,通常可以使用任何一個克隆下來的用戶端來重建服務器上的倉庫(雖然可能會丟失某些服務器端的hook設置,但是所有版本的數據仍在)。
克隆倉庫的命令是git clone。比如,要克隆Git的自建項目HTMLTestRunner,可以用下面的命令:
git clone https://github.com/mingming1205/HTMLTestRunner
這會在當前目錄下創建一個名為“HTMLTestRunner”的目錄,并在這個目錄下初始化一個.git文件夾,從遠程倉庫拉取下所有數據放入.git文件夾,然后從中讀取最新版本的文件的拷貝。
如果打開這個新建的HTMLTestRunner文件夾,會發現所有項目文件已經在里面了,準備就緒等待后續的開發和使用。
如下圖:
圖5
圖6
如果想在克隆遠程倉庫的時候,自定義本地倉庫的名字,可以通過額外的參數指定新的目錄名:
git clone https://github.com/mingming1205/HTMLTestRunner myhtmltestrunner
這會執行與上一條命令相同的操作,但是目標目錄名變成了myhtmltestrunner。
如下圖:
圖7
圖8
Git支持多種數據傳輸協議。以上的例子使用的是https://協議,不過也可以使用git://協議或者使用 SSH 傳輸協議,例如user@server:path/to/repo.git。
至于所有這些協議在服務器端是如何配置使用,以及各種方式之間的利弊請查看“在服務器上搭建 Git”的介紹。
記錄每次更新到倉庫
執行命令:
git commit -m “描述”
查看提交歷史
執行命令:
git log
如果附帶一系列總結的文字,執行命令:
git log --stat
如果限制日志查看數量,執行命令git log -p -2,當退出log時,在冒號“:”后面敲q即可。
以下表格引自官網:
感謝大家的閱讀,希望你們能從中有所收獲!
1)關注+私信回復:“測試”,可以免費領取一份10G軟件測試工程師面試寶典文檔資料。以及相對應的視頻學習教程免費分享!,其中包括了有基礎知識、Linux必備、Mysql數據庫、抓包工具、接口測試工具、測試進階-Python編程、Web自動化測試、APP自動化測試、接口自動化測試、測試高級持續集成、測試架構開發測試框架、性能測試等。
2)關注+私信回復:"入群" 就可以邀請你進入軟件測試群學習交流~~
言
今天我們來講講Pytest+Allure+Jenkins實現Web自動化集成測試,喜歡的小伙伴記得點贊喲。
Pytest介紹
pytest是一個非常成熟的全功能的Python測試框架,主要有以下幾個特點:簡單靈活、容易上手、文檔豐富;支持參數化,可以細粒度地控制被測用例;能夠支持簡單的單元測試和復雜的功能測試,還可以用來做Web自動化(selenium)、APP自動化(appium)以及接口自動化(pytest+requests);pytest具有很多第三方插件,并且可以自動以擴展,比較好用的如pytest-html(完美html測試報告生成)、pytest-rerunfailures(失敗用例重復執行)、pytest-xdist(多CPU分發)等;測試用例的skip和xfail處理;可以很好的和CI工具結合,如:Jenkins。
Pytest安裝
直接在命令窗口執行以下命令即可,更多信息可查閱官方文檔
pip install pytest # 安裝pytest
pytest --version # 查看pytest版本
直接在PyCharm中安裝,下面提到的使用pip安裝方式都可以直接在PyCharm中安裝,安裝成功后點擊【OK】
PyCharm中設置使用pytest
由于PyCharm默認使用Unitest,所以安裝pytest后需要更改默認值,配置路徑如下
配置路徑:依次點擊【File】→【Settings】→【Tools】→【Python Integrated Tools】,【Default test runner】選擇“pytest”,然后點擊【Apply】→【OK】,就可以使用Pytest啦
Pytest使用方法
Pytest規則
編寫pytest測試用例默認使用以下規則,當然,規則是可以修改的
修改規則需添加配置文件pytest.ini,它是pytest的主配置文件,可以修改pytest的默認行為,此文件放在項目的根目錄下才會生效(除非指定目錄查找配置文件),如下配置,注意:實際配置文件中不可出現中文、冒號、引號等
[pytest]
python_files = test_*.py *_test.py case_* # 添加以case_*開頭的測試模塊
python_classes = Test* *_case* # 添加以*_case結尾的測試類
python_functions = test_* case_* # 添加以case_*開頭的測試函數
testpaths = testcases # 指定測試目錄,是指以testpaths所在目錄為基準的相對路徑
addopts = -vs -l # 將常用命令參數設為默認,省去重復輸入的工作
norecursedirs = .* build dist CVS _darcs {arch} *.egg src # 指定pytest忽略查找某些目錄,多個目錄之間空格隔開
log_cli = True # 控制臺實時輸出日志
# 注冊mark標記
markers =
smoke : smoke tests as smoke
output : print
Pytest標記
上面的配置文件中提到了標記,又如何使用呢?
默認情況下,pytest會遞歸查找當前目錄下所有以test開頭或結尾的Python腳本,并執行文件內所有以test開頭的函數和方法。工作中由于功能尚未實現、挑選用例執行冒煙測試等原因,只想測試指定用例,在pytest中有幾種方法可解決
Pytest運行
示例:
# 文件名稱命名規則,以test_開頭或_test結尾
import pytest
def test_func(): # 通常在類外面稱為函數,函數命名規則,以test_開頭
assert 1 == 1
class Testpy(object): # 類命名規則,以Test開頭
def test_method(self): # 通常在類中稱為方法,方法命名規則與函數一樣,以test_開頭
assert 1 + 2 == 3
@pytest.mark.smoke
def test_func1(self):
print("這是Pytest")
@pytest.mark.smoke
class caseCls(object):
def dyd_case(self):
print("修改函數后的規則后")
if __name__ == '__main__':
pytest.main(["test_learn.py"]) # 通過main函數執行命令
使用命令執行示例中的用例
pytest ../Pytest # 執行包中所有模塊的用例
pytest -vs test_learn.py # 執行單獨的pytest模塊,test_learn.py文件
pytest -vs test_learn.py::Testpy # 只執行文件中的Testpy類
pytest -vs test_learn.py::Testpy::test_method # 只執行文件中Testpy類下的test_method方法
pytest -vs test_learn.py::test_function # 只執行文件中test_function函數
pytest -m smoke test_learn.py # 執行帶有smoke標記的用例
pytest -k dyd test_learn.py # 只執行包含關鍵字dyd的用例
pytest --maxfail=2 test_learn.py # 執行指定文件中的用例,失敗用例超出2條則停止執行
pytest --collect-only test_learn.py # 收集指定文件中的用例,不加文件名則直接搜索當前目錄下所有用例
Pytest參數化
在pytest中,可以使用參數化測試,即每組參數都獨立執行一次
使用參數化裝飾器pytest.mark.parametrize(argnames,argvalues),參數化的名字要與方法中的參數名一一對應,傳遞多個參數時可使用列表、元組、字典或列表嵌套等,實際工作中還是以json、yaml、excel等文件形式做參數化的較多,后續再介紹,示例如下:
import pytest # 導入pytest包
list = [1,"1+1","1+2"] # 列表
# ↓參數必須與值的個數相等,可使用ids參數重命名,名字方便理解其意思即可,ids的個數要等于傳遞的數據個數
@pytest.mark.parametrize("value",list,ids=["value=1","value=2","value=3"])
def test_list(value):
print(value) # 打印三個結果
tuple = [("abc"),("def"),["g","h","i"],[1,2,3]] # 元組
@pytest.mark.parametrize("x,y,z",tuple) # 參數必須與值的個數相等
def test_xzy(x,y,z):
print(x,y,z) # 打印四個結果
@pytest.mark.parametrize("input,expect",[("1+1",2),("2+2",4)])
def test_count(input,expect):
assert eval(input) ==expect # 估算實際結果是否與期望結果一致,打印兩個結果
dict = ({"username":"dyd","passwd":123456},{"phone":18888888888,"age":18}) # 字典
@pytest.mark.parametrize("dic",dict)
def test_dict(dic):
print(dic) # 打印兩個結果
data = [ # ↓通過pytest中的param定義參數,id是對參數的一個說明,可自定義,方便理解各用例的含義即可
pytest.param(100,100,200,id="a+b:pass"),
pytest.param("a","b","ab",id="a+b:pass"),
pytest.param(1,1,6,id="a+b:fail")]
def add(a,b): # 定義一個add相加的函數
return a+b
class TestParam(object):
@pytest.mark.parametrize("a,b,expect",data)
def test_param(self,a,b,expect):
assert add(a,b) == expect # 調用a+b,判斷實際結果是否與期望結果一致,出現三個結果
@pytest.mark.parametrize("x",(1,2,3))
@pytest.mark.parametrize("y",(4,5,6))
def test_dkej(x,y):
print(f"打印組合方式:({x},{y})") # 通過參數化實現笛卡爾積
Setup與teardown
在執行用例時,可能某些操作只需要進行一次,比如打開瀏覽器,或者每次操作前都需要先執行其它操作,比如查看數據前需要連接數據庫,查看后需要斷開數據庫等,類似的操作可以使用以下幾種setup/teardown進行配置與銷毀
下面是使用方法簡單示例,setup/teardown并非必須成對使用,比如連接數據庫后不想斷開,就可以只使用setup
def setup_module():
print("setup_模塊級")
def teardown_module():
print("teardown_模塊級")
…… setup_function/teardown_function
def test_01():
print("測試01")
def test_02():
print("測試02")
class Testcase01(object):
@classmethod
def setup_class(cls):
print("setup_類")
def teardown_class(cls):
print("teardown_類")
…… setup_method/teardown_method
…… setup/teardown
def test_03(self):
print("測試03")
def test_04(self):
print("測試04")
下面是兩個函數test_01、02和兩個方法test_03、04,在配置setup和teardown后運行的結果,從結果中可以看出它們的層級關系
setear_test.py::test_01
setup_模塊級
setup_函數
測試用例01 PASSED
teardown_函數
setear_test.py::test_02
setup_函數
測試用例02 PASSED
teardown_函數
setear_test.py::Testcase01::test_03
setup_類
setup_方法
setup
測試用例03 PASSED
teardown
teardown_方法
setear_test.py::Testcase01::test_04
setup_方法
setup
測試用例04 PASSED
teardown
teardown_方法
teardown_類
teardown_模塊級
Pytest fixture
上面setup/teardown可實現的功能,fixture可以更靈活的實現
定義fixture和定義普通函數差不多,唯一區別是在函數上加上個裝飾器@pytest.fixture()
為了跟用例有所區分,fixture命名時不要以test開頭,fixture是有返回值的,若沒有返回值則默認為None
用例調用fixture的返回值,直接把fixture的函數名當作變量名
import pytest
@pytest.fixture() # 默認范圍為函數級(function)
def login():
print("請先登錄")
return
def test_Search(): # 不需要登錄,所以不調用fixture
print("搜索商品,無需登錄")
def test_Cart(login): # 需要登錄,調用fixture
print("加購商品,需登錄")
@pytest.fixture(scope="class") # 設置范圍為類級(class)
def login():
print("請登錄后再購買")
return
class Testfix(object):
def test_Look(self):
print("查看商品,無需登錄") # 不需要登錄,所以不調用fixture
def test_Pay(self,login):
print("購買商品,需登錄") # 需要登錄,調用fixture
輸出結果如下,控制范圍(scope)還有module,package,session,以及其它參數如:param、ids、name等
test_fix.py::test_Search
搜索商品,無需登錄 PASSED
test_fix.py::test_Cart
請登錄后再購買
加購商品,需登錄 PASSED
test_fix.py::Testfix::test_Look
查看商品,無需登錄 PASSED
test_fix.py::Testfix::test_Pay
請登錄后再購買
購買商品,需登錄 PASSED
再介紹一下session級別,它是可以跨.py模塊調用的,也就是說有多個.py文件的測試用例時,只需調用一次fixture,設置scope="session",并寫在conftest.py文件中,conftest.py文件是固定名稱,pytest會自動識別此文件,所以不可改名稱,此文件放在項目根目錄,則可全局調用,放在某個包中,則只對包內的有效
比如使用鉤子函數實現失敗用例截圖,將以下代碼寫在conftest.py中,其它模塊就可以直接調用
import allure
import pytest
from selenium import webdriver
driver = None # 自定義一個driver=None
@pytest.hookimpl(tryfirst=1,hookwrapper=1)
def pytest_runtest_makereport(item,call): # 鉤子函數
# 用例執行完成后再執行此操作,(后置處理用yield)
outcome = yield # 測試用例執行完后接下來要做什么事情
rep = outcome.get_result() # 獲取用例執行完成之后的結果
if rep.when == "call" and rep.failed: # 若結果正在被調用而且是失敗的則進行截圖
img = driver.get_screenshot_as_png() # 若出現異常,則進行截圖操作
allure.attach(img, "失敗截圖", allure.attachment_type.PNG) # 將圖片展現在Allure報告上
# 自定義一個Fixture,初始化driver對象
@pytest.fixture(scope="session",autouse=True)
def init_driver():
global driver
driver = webdriver.Chrome()
return driver # 返回初始化后的driver,就可以直接被調用啦
調用conftest.py中的函數
def test_baidu(init_driver):
init_driver.get("http://baidu.com")
init_driver.find_element(By.CLASS_NAME, "123").click()
……
Pytest Allure
Allure安裝
Allure運行需要Java環境,Java安裝并配置環境變量后,在命令窗口執行以下命令,更多信息可查閱官方文檔
pip install allure-pytest
安裝完成后,下載一個allure可執行文件,點擊此次進入下載列表頁,下載所需版本,下載后解壓文件,然后將bin目錄加到PATH環境變量中,最后在命令行窗口輸入allure或者allure --version驗證是否配置成功
Allure用例描述
添加裝飾器 | 參數值 | 參數說明 |
@allure.epic() | epic描述 | 定義項目,往下是feature |
@allure.feature() | 模塊名稱 | 大的功能點描述,往下是story |
@allure.story() | 次級分類 | 用戶故事,次級功能點描述,往下是title |
@allure.title() | 用例的標題 | 測試用例重命名 |
@allure.testcase() | 測試用例的鏈接地址 | 對應功能測試用例系統里面的用例 |
@allure.issue() | 測試用例的缺陷地址 | 對應缺陷管理系統里面的鏈接 |
@allure.description() | 用例描述 | 測試用例的描述 |
@allure.step() | 操作步驟 | 測試用例的步驟 |
@allure.severity() | 用例等級 | blocker,critical,normal,minor,trivial |
@allure.link() | 鏈接 | 定義一個鏈接,在測試報告展現 |
@allure.attach() | 附件 | 報告添加附件,支持html、圖片、視頻 |
Allure報告生成
生成測試報告必須在命令行執行
示例如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import pytest
import allure
from util import util # 導入自己封裝的日志模塊
loginError = [["","654321","賬號不能為空"],["test","123456","用戶名不正確。"],
["admin","","密碼不能為空"],["admin","654321","用戶名或密碼不正確"]]
loginOK = [["admin","123456","用戶中心"]]
@allure.feature("Jpress后端測試")
class TestUser(object):
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://192.166.66.22:8080/user/login")
self.logger = util.get_logger()
self.logger.info("登錄測試")
@allure.story("這是登錄失敗的測試用例")
@allure.description("登錄平臺-錯誤場景")
@pytest.mark.parametrize("username,pwd,expected",loginError)
def test_user_login_Error(self,username,pwd,expected):
user = username
pwd = pwd
expected = expected
# 清空輸入框后輸入用戶名
self.driver.find_element(By.NAME, "user").clear()
self.driver.find_element(By.NAME, "user").send_keys(user)
# 清空輸入框后輸入密碼
self.driver.find_element(By.NAME, "pwd").clear()
self.driver.find_element(By.NAME, "pwd").send_keys(pwd)
# 點擊【登錄】
self.driver.find_element(By.CLASS_NAME, "btn").click()
WebDriverWait(self.driver, 3).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
# 驗證報錯信息是否正確
assert alert.text == expected
self.logger.debug("登錄失敗,用戶名或密碼輸出有誤!")
alert.accept()
@allure.story("后臺管理平臺登錄失敗")
@allure.description("記錄失敗時的截圖和日志")
def test_failcase(self):
self.driver = webdriver.Chrome()
self.driver.get("http://192.166.66.22:8080/admin/login")
self.driver.find_element(By.NAME, "user").send_keys("admin")
self.driver.find_element(By.NAME, "pwd").send_keys("123456")
self.driver.find_element(By.NAME, "captcha").send_keys(8888)
try:
self.driver.find_element(By.CLASS_NAME, "btn錯誤的登錄按鈕元素").click()
except Exception as e:
img = self.driver.get_screenshot_as_png() # 若出現異常,則進行截圖操作
allure.attach(img, "失敗截圖", allure.attachment_type.PNG) # 將圖片展示在Allure報告上
log = self.logger.error("報錯信息:%s", "無法登錄,找不到登錄按鈕", exc_info=1) # 記錄報錯日志
# 獲取報錯日志,并將日志展示在Allure報告上
allure.attach.file(self.driver.get_log(log), "失敗日志", allure.attachment_type.TEXT)
WebDriverWait(self.driver, 3).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
assert alert.text == "登錄失敗"
@allure.story("這是登錄成功用例")
@allure.description("成功登錄至平臺")
@allure.severity(severity_level="Blocker")
@pytest.mark.parametrize("username,pwd,expected",loginOK)
def test_user_login_OK(self,username,pwd,expected):
user = username
pwd = pwd
expected = expected
self.driver.find_element(By.NAME, "user").clear()
self.driver.find_element(By.NAME, "user").send_keys(user)
self.driver.find_element(By.NAME, "pwd").clear()
self.driver.find_element(By.NAME, "pwd").send_keys(pwd)
self.driver.find_element(By.CLASS_NAME, "btn").click()
WebDriverWait(self.driver, 3).until(EC.title_is(expected))
assert self.driver.title == expected
@allure.story("文章管理測試用例")
@allure.title("查看文章列表")
@allure.step("步驟1:進入文章列表")
def test_article_list(self):
expected = "http://192.166.66.22:8080/ucenter/article"
self.driver.find_element(By.XPATH,'//span[contains(text(),"我的文章")]').click()
self.driver.find_element(By.LINK_TEXT,"文章列表").click()
WebDriverWait(self.driver, 2).until(EC.url_contains("/ucenter/article"))
assert self.driver.current_url == expected
@allure.story("文章管理測試用例")
@allure.title("查看文章詳情")
@allure.step("步驟2:查看文章詳情")
@allure.severity(severity_level="critical")
def test_Look_article(self):
expected = "一個小測試"
handle = self.driver.current_window_handle # 獲取當前窗口句柄
self.driver.find_element(By.LINK_TEXT, "一個小測試").click()
handles = self.driver.window_handles # 獲取所有窗口句柄
for newhandle in handles: # 對窗口進行遍歷
if newhandle != handle: # 判斷當前窗口是否為新窗口
self.driver.switch_to.window(newhandle) # 切換到新打開的窗口
WebDriverWait(self.driver, 2).until(EC.title_is(expected))
assert self.driver.title == expected
# 關閉瀏覽器
self.driver.quit()
@allure.feature("Jpress前端測試")
class TestBlog(object):
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://192.166.66.22:8080/")
self.logger = util.get_logger()
self.logger.info("博客訪問測試")
@allure.title("查看博客詳情")
@pytest.mark.skipif(reason="刻意跳過此用例")
def test_details(self):
expected = "一個小測試"
self.driver.find_element(By.CLASS_NAME,"bh-card-main-title").click()
WebDriverWait(self.driver, 2).until(EC.url_contains("/article/2"))
assert self.driver.title == expected
# 關閉瀏覽器
self.driver.quit()
下圖是生成的Allure報告用例執行結果
數據驅動測試(DDT)
讀取excel文件
需要安裝xlrd模塊,使用xlrd模塊處理excel文件,新版xlrd不支持xlsx格式的excel,會報錯xlrd.biffh.XLRDError: Excel xlsx file; not supported,可以使用xls格式的excel,或者可以安裝老版本的xlrd
pip install xlrd==1.2.0 # 此版本支持xlx格式的excel
結合pytest的參數化的方式,實現excel文件數據驅動,示例如下:
import pytest
import xlrd
def get_data(): # 定義一個獲取數據的函數
filename = "my_data.xlsx" # 定義數據文件
wb = xlrd.open_workbook(filename) # 打開文件
sheet = wb.sheet_by_index(0) # 使用索引方式獲得文件中的第一個sheet
rows = sheet.nrows # 獲取行
cols = sheet.ncols # 獲取列
lst = []
for row in range(rows): # 遍歷行
for col in range(cols): # 遍歷列
cell_data = sheet.cell_value(row,col) # 獲取單元格中的數據
lst.append([cell_data]) # 將單元格中的數添加到列表中
return lst # 返回list列表
@pytest.mark.parametrize("value",get_data()) # 調用excel數據
def test_read(value):
print(value)
# 輸出結果,2*2的表格,打印每個單元格中的數據
test_excel.py::test_read[value0] PASSED [ 25%]['xlsx']
test_excel.py::test_read[value1] PASSED [ 50%]['格式']
test_excel.py::test_read[value2] PASSED [ 75%]['讀取文件']
test_excel.py::test_read[value3] PASSED [100%]['666']
讀取csv文件
csv文件是使用逗號分隔的文本文件,直接使用python的csv模塊處理csv文件,然后結合pytest的參數化的方式,實現csv文件數據驅動,
示例如下:
# 測,試
# ceshi,testing
import csv
import pytest
def get_data():
with open("my_data.csv","r",encoding='UTF-8') as j: # 只讀模式打開csv文件
data = csv.reader(j) # csv.reader(f)返回一個csv_reader對象
lst = []
for row in data: # 遍歷對象,每次返回一行
lst.extend(row) # 將數據一次性追加到lst中,將結果寫到一個列表中
return lst # 返回lst
@pytest.mark.parametrize("csv_value",get_data()) # 調用csv數據
def test_read(csv_value):
print(csv_value) # 將寫在列表中的數據一個一個的輸出
# 輸出結果
test_csv.py::test_read[\u6d4b] PASSED [ 25%]測
test_csv.py::test_read[\u8bd5] PASSED [ 50%]試
test_csv.py::test_read[ceshi] PASSED [ 75%]ceshi
test_csv.py::test_read[testing] PASSED [100%]testing
讀取json文件
直接使用python中的json模塊處理json文件,然后結合pytest的參數化方式,實現json文件數據驅動
json文件內容
[
{
"name":"",
"pwd":"654321",
"expected":"賬號不能為空"
},
{
"name":"admin",
"pwd":"",
"expected":"密碼不能為空"
},
{
"name":"admin",
"pwd":"654321",
"expected":"用戶名或密碼不正確"
}
]
示例如下:
import pytest
import json
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def get_data():
lst = []
with open("my_data.json","r",encoding='UTF-8') as j: # 只讀模式打開json文件
dict_data = json.loads(j.read()) # 將json轉換為字典
for i in dict_data: # 遍歷字典
lst.append(tuple(i.values())) #將數據以元組形式添加到lst中
return lst # 返回lst
# 此時輸出get_data()值,會得到的下面結果
[('', '654321', '賬號不能為空'), ('admin', '', '密碼不能為空'), ('admin', '654321', '用戶名或密碼不正確')]
class TestUser(object):
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://192.166.66.22:8080/user/login")
@pytest.mark.parametrize("username,pwd,expected",get_data()) # 調用json數據
def test_user_login_Error(self,username,pwd,expected):
user = username
pwd = pwd
expected = expected
# 清空輸入框后輸入用戶名
self.driver.find_element(By.NAME, "user").clear()
self.driver.find_element(By.NAME, "user").send_keys(user)
# 清空輸入框后輸入密碼
self.driver.find_element(By.NAME, "pwd").clear()
self.driver.find_element(By.NAME, "pwd").send_keys(pwd)
# 點擊【登錄】
self.driver.find_element(By.CLASS_NAME, "btn").click()
# 等待頁面加載
WebDriverWait(self.driver, 3).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
# 驗證報錯信息是否正確
assert alert.text == expected
alert.accept()
讀取yaml文件
先安裝yaml模塊,然后結合pytest的參數化方式,實現yaml文件數據驅動,和json差不多
pip install pyyaml
yaml文件內容
---
name: ""
pwd: "123456"
expected: "賬號不能為空"
---
name: "admin"
pwd: ""
expected: "密碼不能為空"
---
name: "admin"
pwd: "654321"
expected: "用戶名或密碼不正確"
使用yaml驗證登錄,示例如下:
import pytest
import yaml
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def get_data():
lst = []
with open("my_data.yaml","r",encoding='UTF-8') as j: # 只讀模式打開yaml文件
ym = yaml.load_all(j.read()) # 使用load_all生成迭代器
for i in ym: # 遍歷ym中的數據
lst.append(tuple(i.values())) #將數據以元組形式添加到lst中
return lst # 返回lst
# 此時輸出get_data()值,會得到和讀取json文件一樣的結果
[('', '123456', '賬號不能為空'), ('admin', '', '密碼不能為空'), ('admin', '654321', '用戶名或密碼不正確')]
class TestUser(object):
def setup_class(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("http://192.166.66.22:8080/user/login")
@pytest.mark.parametrize("username,pwd,expected",get_data()) # 調用yaml數據
def test_user_login_Error(self,username,pwd,expected):
user = username
pwd = pwd
expected = expected
# 清空輸入框后輸入用戶名
self.driver.find_element(By.NAME, "user").clear()
self.driver.find_element(By.NAME, "user").send_keys(user)
# 清空輸入框后輸入密碼
self.driver.find_element(By.NAME, "pwd").clear()
self.driver.find_element(By.NAME, "pwd").send_keys(pwd)
# 點擊【登錄】
self.driver.find_element(By.CLASS_NAME, "btn").click()
# 等待頁面加載
WebDriverWait(self.driver, 3).until(EC.alert_is_present())
alert = self.driver.switch_to.alert
# 驗證報錯信息是否正確
assert alert.text == expected
alert.accept()
Jenkins集成Allure報告
本次Jenkins是安裝在Windows上的,直接Jenkins官網下載安裝包進行安裝就行啦,不多做介紹
2.進入全局配置,配置Allure Commandline,填寫本地Allure安裝路徑,別名自定義,完成后點擊【應用】→【保存】
3.新建一個自由風格的項目
4.配置項目,在常規配置里點擊【高級】,勾選“使用自定義的工作空間”,填寫工作空間目錄(通常填寫項目的主目錄),顯示名稱自定義
然后增加構建步驟,選擇“執行windows批處理命令”,填寫要執行的命令,命令可以指定文件或類等,具體上文有介紹
pytest -vs --alluredir=./pytest_result test_Jpress.py --clean-alluredir
最后增加構建后操作步驟,選擇“Allure Report”,填寫結果路徑,一定要與構建時的路徑相同,然后【應用】→【保存】
8.在Jenkins頁面上會出現Allure報告標識,點擊可查看具體構建報告
報告結果如下圖所示
好了今天的分享就到這了,喜歡的記得關注點贊喲
*請認真填寫需求信息,我們會在24小時內與您取得聯系。