安装部署
在敏捷开发中,经常会听到TDD,BDD这些词语,对于如何进行测试驱动开发,不同的敏捷团队有不同的执行方式,针对于目前在iOS下的测试方案,我们搭建了iOS的自动化测试平台。
需要的安装文件(以下文件放到同一个目录下面,我的命名是setup_cucumber):
1.Frank 源代码 (可以从https://github.com/moredip/Frank下载,该项目用于为本地iOS应用做自动化行为测试)
2.必要的.gem档案 (如果有更新版本的.gem档,可以进行替换)
builder-3.0.0.gem
cucumber-0.10.2.gem
diff-lcs-1.1.2.gem
frank-cucumber-0.6.1.gem
gherkin-2.3.7.gem
json-1.5.2.gem
rack-1.2.2.gem
rspec-2.5.0.gem
rspec-core-2.5.2.gem
rspec-expectations-2.5.0.gem
rspec-mocks-2.5.0.gem
sim_launcher-0.3.0.gem
sinatra-1.2.6.gem
term-ansicolor-1.0.5.gem
tilt-1.3.gem
3.install.sh
#!/bin/sh
sudo gem install *.gem
安装很简单,执行install.sh文件就可以了
1.打开Terminal,进入setup_cucumber目录
2.执行 ./install.sh
如果在安装过程出现问题,反复执行几次就可以了。
开始我们的自动化测试之旅
1.建立一个新的 Target ,命名为 Demo-Frank
2.在项目目录下新建Frank目录,将Frank的源代码复制进来,然后把所有的lib,src 和 resources 添加到Demo-Frank这个Traget
3.添加CFNetwork.framework 到Demo-Frank这个Traget
4.在Demo-Frank这个Traget的"Other Linker Flags"设置项下加入一个flag, "-ObjC"(不要带引号)
5.修改main.m中代码,如下:
#import <UIKit/UIKit.h>
#ifdef FRANK
#include "FrankServer.h"
static FrankServer *sFrankServer;
#endif
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#ifdef FRANK
sFrankServer = [[FrankServer alloc] initWithDefaultBundle];
[sFrankServer startServer];
#endif
int retVal = UIApplicationMain(argc, argv, nil, @"YouProjectAppDelegate");
[pool release];
return retVal;
}
6.开启accessibility功能。在OSX下,进入System Preferences -> Universal Access,然后选中"Enable access for assistive devices"。在模拟器下,进入Settings -> General -> Accessibility -> Accessibility Inspector 选择"on"。
7.在 Demo-Frank 这个 Target 下进入 Run Script, 在 shell 后面的输入框中键入 /bin/sh, 在 shell 下面的输入框中输入
echo "Copying build to FrankDeploy directory"
eche ${BUILD_DIR}
ditto "${BUILD_DIR}/Debug-iphonesimulator/YourProject.app"
"./FrankDeploy/YourProject_Frank.app"
8.编译运行Demo-Frank,(如果存在通过网络连接获取数据,确保能正常连接,注意防火墙的设定),然后进入你要测试的场景界面。
9.打开浏览器,输入http://localhost:37265,点击右上角的Refresh按钮,当载入完毕后可以看到所有这个界面的elements信息(每次重启Demo-Frank或者要切换测试场景的时候都需要点击Refresh按钮,去获取当前的elements信息)。
如上图所示,当前页面有一个UILabel,它的accessibilityLabel被设置为"UserID:",可以在elements tree西面找到该element。然后在页面最上方"View DOM"的Selector中输入"label marked:'UserID:'",然后点击Flash,在Xcode的输出窗口中可以看到相应的输入信息,如果输入一个不存在的Selector将会弹出提示,告知你当前的元素不存在。
在"Accessibility Elements"当中,会显示当前所有设置有AccessibilityLabel属性element,缩放浏览器和模拟器,让他们能在一个桌面上完全呈现,点击某一个element,看看有什么神奇的效果? 你点中的那个element,在界面上会闪动!
开始编写自动化测试代码
1.在项目目录下新建features目录,该目录用于放置所有需要运行自动化测试的内容。features目录下面新建2个目录step_definitions和support。
2.在support目录下新建一个env.rb文件,其内容如下
require 'frank-cucumber'
3.在step_definitions目录下新建lunch_steps.rb,其内容如下
Given /^I launch the app$/ do
# kill the app if it's already running, just in case this helps
# reduce simulator flakiness when relaunching the app. Use a timeout of 5 seconds to
# prevent us hanging around for ages waiting for the ping to fail if the app isn't running
begin
Timeout::timeout(5) { press_home_on_simulator if frankly_ping }
rescue Timeout::Error
end
require 'sim_launcher'
app_path = ENV['APP_BUNDLE_PATH'] || app_bundle_path
simulator_version = ENV['IOS_SIMULATOR_VERSION'] || "5.0"
raise "APP_BUNDLE_PATH was not set. \nPlease set a APP_BUNDLE_PATH ruby constant or environment variable to the path of your compiled Frankified iOS app bundle" if app_path.nil?
if( ENV['USE_SIM_LAUNCHER_SERVER'] )
simulator = SimLauncher::Client.for_ipad_app( app_path, simulator_version )
else
simulator = SimLauncher::DirectClient.for_ipad_app( app_path, simulator_version )
end
num_timeouts = 0
loop do
begin
simulator.relaunch
wait_for_frank_to_come_up
break # if we make it this far without an exception then we're good to move on
rescue Timeout::Error
num_timeouts += 1
puts "Encountered #{num_timeouts} timeouts while launching the app."
if num_timeouts > 3
raise "Encountered #{num_timeouts} timeouts in a row while trying to launch the app."
end
end
end
# TODO: do some kind of waiting check to see that your initial app UI is ready
# e.g. Then "I wait to see the login screen"
end
3.在feature目录下新建demo.feature,其内容如下
Scenario: When I lunch the app
Then I should see the "UserID:" label
4.在step_definitions目录下新建login.rb,其内容如下
Then /^I should see the "([^"]*)" label$/ do |name|
check_element_exists("label marked:'#{name}'")
end
5.打开Terminal,进入项目目录,输入cucumber demo.feature,即可进行自动测试,如果有多个feature文件需要进行测试,直接输入cucumber,即可对features目录下的所有feature文件进行测试
写在最后,在自动化测试的过程中,我们需要熟悉Ruby,在feature文件中实际上我们写的就是一些模拟的用户行为,在rb文件中实际上我们写的是针对于这些行为做的解析和动作。过段时间,针对如何写feature和rb会有更加详细的说明。