什么是Function Testing(摘自wikipedia)
Functional testing is a quality assurance (QA) process and a type of black-box testing that bases its test cases on the specifications of the software component under test. Functions are tested by feeding them input and examining the output, and internal program structure is rarely considered (not like in white-box testing). Functional testing usually describes what the system does.
為什么需要Functional Testing
在討論這個(gè)問題前先來一些對比:
-
Functional Tesing vs Unit Testing
Unit Testing關(guān)注點(diǎn)在于單獨(dú)的代碼片段,可信度較高且易擴(kuò)展,是從開發(fā)者的視角來編寫的。相對Functional Testing來說更快,你可以很快地為某段代碼編寫測試,執(zhí)行速度快,能夠更快的定位bug。但是它并不關(guān)心產(chǎn)品的業(yè)務(wù)邏輯,所以當(dāng)單元測試通過并不能保證你的產(chǎn)品能夠滿足業(yè)務(wù)需求。
-
Functional Testing vs Integration Testing
Integration Testing主要用于不同module、system等之間的集成測試。Unit Testing用于保證每個(gè)代碼片段能夠獨(dú)立地正確工作,但是并不能保證他們集成在一起能夠正確工作。你需要集成測試將不同的功能模塊集成在一起來進(jìn)行測試。但是相對Functional Testing來說它還是不能保證某個(gè)feature能夠得到預(yù)期的結(jié)果。
下面的Test Pyramid摘自Martin Fowler的 文章,越高層次產(chǎn)生的用戶價(jià)值會(huì)更高且更慢,越低層次的產(chǎn)生的價(jià)值更低且更快,你所寫的任何一行單元測試代碼對于你的用戶來說都是不可見的,他能感知到的只能通過UI來體現(xiàn)。可以看出我們需要很多的單元測試來保證我們的代碼質(zhì)量,這對開發(fā)人員來說是有巨大價(jià)值的,它能夠幫開發(fā)人員快速發(fā)現(xiàn)且定位問題。
Funtional testing 屬于UI測試,UI測試包含行為和外觀。Functional testing從用戶行為這個(gè)維度來保證了代碼的質(zhì)量。比如我需要對用戶登錄進(jìn)行測試,我需要測試的點(diǎn)就可能涵蓋用戶點(diǎn)擊了登錄,需要看到界面上有相應(yīng)的提示,成功之后需要到達(dá)主界面等。
BDD 與 Functional Testing
在敏捷實(shí)踐中我們通過BDD(Behavior-driven development)來幫助我們完成Functional testing。BDD鼓勵(lì)軟件項(xiàng)目中的開發(fā)者、QA和非技術(shù)人員或商業(yè)參與者之間的協(xié)作,讓其能夠在一個(gè)共同的基礎(chǔ)上達(dá)成共識(shí)。
BDD的框架很多,下面簡單的羅列了一下:
框架 | 語言 |
---|---|
Cucumber | Ruby |
JBehave | Java |
RBehave | Ruby |
Specflow | C# |
它們基本上都是基于Gherkin作為DSL在不同語言上的實(shí)現(xiàn),讓我們可以用自然語言去書寫我們的代碼。
用BDD來為某個(gè)feature書寫測試通常包含以下幾個(gè)部分:
- 一個(gè)簡單的Title
- 對測試場景進(jìn)行簡單描述
- 驗(yàn)收步驟以及預(yù)期行為的描述
在對驗(yàn)收步驟進(jìn)行描述的時(shí)候通常會(huì)用到這樣的格式"Given ... When ... Then ",各自的含義如下
- Given: 測試的前置條件
- When: 指定用戶的行為
- Then: 驗(yàn)證結(jié)果
因此,如果用這樣的格式去描述用戶登錄的場景就大概應(yīng)該是:
- Given 用戶打開登錄界面
- When 用戶填寫賬號和密碼后點(diǎn)擊登錄按鈕
- Then 用戶登錄成功來到主界面。
當(dāng)然除了這幾個(gè)關(guān)鍵字,可能你還會(huì)接觸到And、But、Or等,使用它們可以增加代碼的可讀性。
通過自然語言的描述,業(yè)務(wù)專家、QA或者其他沒有技術(shù)背景的人也可以很明確地明白這個(gè)測試是在干什么。
針對于iOS開發(fā),蘋果本身的XCTest不能很好的支持我們寫Functional testing。它基于assert來完成測試,而很多時(shí)候assert所表達(dá)的含義也很難理解,同時(shí)它相對來說也比較難mock。所以我們可能還需要一些工具來方便我們寫Functional Testing。
下面簡單的列了一些iOS開發(fā)中能夠用來UI Testing的框架:
框架 | 語言 | 支持平臺(tái) |
---|---|---|
Calabash | Gherkin \ Ruby | iOS \ Android |
EarlGrey | OC \ Swift | iOS |
Frank | Gherkin \ Ruby | iOS \ MAC |
KIF | OC \ Swift | iOS |
UI Test | OC \ Swift | iOS |
Calabash和Frank都是基于Cucumber,但是Calabash有著更豐富的特性,比如更豐富的內(nèi)建步驟、更多的手勢支持等,支持的平臺(tái)也更加豐富,使用范圍更廣。
EarlyGrey是google推出的,內(nèi)建同步機(jī)制,測試會(huì)在與UI進(jìn)行交互前自動(dòng)等待動(dòng)畫、網(wǎng)絡(luò)請求等事件,當(dāng)然它還是允許你手動(dòng)處理同步。它會(huì)確保執(zhí)行動(dòng)作前,UI處于穩(wěn)定的狀態(tài)。EarlGrey基于XCTest,因此在Xcode中你可以很容易的建立一個(gè)測試用例類。當(dāng)然在我寫下這篇文章的時(shí)候它還存在一些問題,比如不支持3D Touch,不能和Address Sanitizer一起工作等,完整的列表在這里。
具體使用哪種工具大家可以根據(jù)自己項(xiàng)目的實(shí)際情況來考慮,我目前的項(xiàng)目中使用的是Calabash。
使用Calabash-iOS寫Functional Testing
要想在你的iOS工程中使用Calabash你需要一定的步驟安裝依賴包以及配置工程,可以移步到Calabash查看具體的步驟。
一切都設(shè)置好了之后,工程目錄下會(huì)多一個(gè)叫features的目錄,顧名思義里面會(huì)包含你需要測試的feature。
比如我需要對登錄進(jìn)行測試。我在目錄下新建一個(gè)叫做login.feature
的文件,然后開始描述測試的用戶場景:
Feature: User login flow
Scenario: User can login with correct account number and password
Given I can open the login page
When I type "myname" into the account number input field
And I type "mypassword" into the password input field
And I click then login button
Then I can login successful and see home page
另外,Calabash內(nèi)建了很多的steps,但是不一定額能夠完全滿足你的需求,你可能還需要一些自定義的步驟,自定義的步驟都放在step_definitions里面。
比如我需要定義輸入賬號這個(gè)步驟:
When(/^I type "(.*?)" i into the account number input field$/) do |value|
@login_page.touch_account_field
keyboard_enter_text value
end
當(dāng)描述好feature,并且定義好了步驟之后,這樣一個(gè)用例測試就完成了,接下來你可以通過cucumber
命令來執(zhí)行它。
為了方便調(diào)試,Calabash還提供一個(gè)的命令行工具,通過命令calabash-ios console
來使用。
比如你要查找出當(dāng)前成為焦點(diǎn)的輸入框,然后讓它停止輸入狀態(tài),你可以像下面這個(gè)樣子
query "textField isFirstResponder:1", :resignFirstResponder
在這里支持的命令和在step定義里支持的命令是一樣的,所以在你不確定的時(shí)候,可以通過命令行工具快速的檢驗(yàn)一下。
最后
在CI中加入U(xiǎn)I的自動(dòng)化測試,可以的降低時(shí)間成本提升生產(chǎn)力。但是這并不是銀彈,還得結(jié)合自身項(xiàng)目,用多少,怎么用都得仔細(xì)去考慮。