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.
在讨论这个问题前先来一些对比:
下面的Test Pyramid摘自Martin Fowler的 文章,越高层次产生的用户价值会更高且更慢,越低层次的产生的价值更低且更快,你所写的任何一行单元测试代码对于你的用户来说都是不可见的,他能感知到的只能通过UI来体现。可以看出我们需要很多的单元测试来保证我们的代码质量,这对开发人员来说是有巨大价值的,它能够帮开发人员快速发现且定位问题。
Test Pyramid
Funtional testing 属于UI测试,UI测试包含行为和外观。Functional testing从用户行为这个维度来保证了代码的质量。比如我需要对用户登录进行测试,我需要测试的点就可能涵盖用户点击了登录,需要看到界面上有相应的提示,成功之后需要到达主界面等。
在敏捷实践中我们通过BDD(Behavior-driven development)来帮助我们完成Functional testing。BDD鼓励软件项目中的开发者、QA和非技术人员或商业参与者之间的协作,让其能够在一个共同的基础上达成共识。
BDD的框架很多,下面简单的罗列了一下:
框架 | 语言 |
---|---|
Cucumber | Ruby |
JBehave | Java |
RBehave | Ruby |
Specflow | C# |
它们基本上都是基于Gherkin作为DSL在不同语言上的实现,让我们可以用自然语言去书写我们的代码。
用BDD来为某个feature书写测试通常包含以下几个部分:
在对验收步骤进行描述的时候通常会用到这样的格式"Given ... When ... Then ",各自的含义如下
因此,如果用这样的格式去描述用户登录的场景就大概应该是:
当然除了这几个关键字,可能你还会接触到And、But、Or等,使用它们可以增加代码的可读性。 通过自然语言的描述,业务专家、QA或者其他没有技术背景的人也可以很明确地明白这个测试是在干什么。
针对于iOS开发,苹果本身的XCTest不能很好的支持我们写Functional testing。它基于assert来完成测试,而很多时候assert所表达的含义也很难理解,同时它相对来说也比较难mock。所以我们可能还需要一些工具来方便我们写Functional Testing。
下面简单的列了一些iOS开发中能够用来UI Testing的框架:
框架 | 语言 | 支持平台 |
---|---|---|
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有着更丰富的特性,比如更丰富的内建步骤、更多的手势支持等,支持的平台也更加丰富,使用范围更广。
EarlyGrey是google推出的,内建同步机制,测试会在与UI进行交互前自动等待动画、网络请求等事件,当然它还是允许你手动处理同步。它会确保执行动作前,UI处于稳定的状态。EarlGrey基于XCTest,因此在Xcode中你可以很容易的建立一个测试用例类。当然在我写下这篇文章的时候它还存在一些问题,比如不支持3D Touch,不能和Address Sanitizer一起工作等,完整的列表在这里。
具体使用哪种工具大家可以根据自己项目的实际情况来考虑,我目前的项目中使用的是Calabash。
要想在你的iOS工程中使用Calabash你需要一定的步骤安装依赖包以及配置工程,可以移步到Calabash查看具体的步骤。
一切都设置好了之后,工程目录下会多一个叫features的目录,顾名思义里面会包含你需要测试的feature。
比如我需要对登录进行测试。我在目录下新建一个叫做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内建了很多的steps,但是不一定额能够完全满足你的需求,你可能还需要一些自定义的步骤,自定义的步骤都放在step_definitions里面。 比如我需要定义输入账号这个步骤:
When(/^I type "(.*?)" i into the account number input field$/) do |value|
@login_page.touch_account_field
keyboard_enter_text value
end
当描述好feature,并且定义好了步骤之后,这样一个用例测试就完成了,接下来你可以通过cucumber
命令来执行它。
为了方便调试,Calabash还提供一个的命令行工具,通过命令calabash-ios console
来使用。
比如你要查找出当前成为焦点的输入框,然后让它停止输入状态,你可以像下面这个样子
query "textField isFirstResponder:1", :resignFirstResponder
在这里支持的命令和在step定义里支持的命令是一样的,所以在你不确定的时候,可以通过命令行工具快速的检验一下。
在CI中加入UI的自动化测试,可以的降低时间成本提升生产力。但是这并不是银弹,还得结合自身项目,用多少,怎么用都得仔细去考虑。