热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

2015年iOS测试现状

本文由伯乐在线-nathanw翻译,dopcn校稿。未经许可,禁止转载!英文出处:www.mokacoding.com。欢迎加入翻译小组。几周前,我决定将将我在mokacoding

几周前,我决定将将我在 mokacoding 上的创作更多集中在单元测试与验收测试,自动化和生产效率上,主要在iOS领域。

相关深入文章可以看看“通过 CocoaPods 为 iOS 项目创建 Calabash 并构建配置”和“用终端运行 Xcode 测试”。

这周我们要回过头来看看,或者说是站在更高的角度审视单元测试和验收测试,以及在云端运行持续集成有哪些资源。

就像有人创建 walking skeleton 时会做的事情一样,我们也将先查看 Cocoa 和 Xcode 提供给开发者的工具,然后再看看能实现更好效果的开源库,最后整理出在云端持续集成环境运行测试的解决方案。

Xcode,测试开始的地方

伴随着 iOS 7 和 Xcode 5,苹果发布了 XCTest,一个简单而又强大的测试编写框架,使用了同 xUnit 一样的风格。

编写 XCTest 测试很简单,开发者在 Xcode 点击 ?U 运行测试便能持续不断地迅速获得反馈。

Xcode 还有一个叫“Test Navigator”的界面,它可以让我们看到所有测试点,包括在最后一次运行后的成功或失败状态。

技术分享

值得注意的是,红色为测试失败,绿色为测试通过。在不断迭代过程中颜色会给你很大帮助。

XCTest 已经高度集成在 Xcode 中,使用简单方便。这是它主要优点,也是缺点。XCTAssert 类 API 并不容易理解,也不灵活。从 Xcode 外边运行测试也没有你想象的那么简单。

在过去两年中,iOS 和 OS X 的单元测试框架已经变得越来越好,而验收测试这边反而没什么进步。

苹果提供了 UIAutomation 框架来编写 UI 自动化测试。UIAutomation 测试使用 Javascript 写成。允许用户使用代码驱动应用 UI 并给它的状态设置断言。尽管看上去很美好,使用 UIAutomation 其实是很繁琐的, Javascript API 也没有原生代码写成的单元测试那样强大。

这是 UIAutomation 测试的一个小片段。

1
2
3
4
5
UIATarget.localTarget().frontMostApp().navigationBar().buttons()["Add"].tap();
 
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].cells()[0].elements()["Chocolate Cake"];
 
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[0].scrollToElementWithPredicate("name beginswith ‘Turtle Pie‘");

你可以看到的,Javascript API 比 Foundation 中的那些更加冗长。再加上这种测试需要在 Instruments 中运行,你就可以想象使用这个框架是多么的不爽。

最后是苹果的 CI 解决方案:Xcode Bots。我们可以配置一个 Xcode Bot,在需要的时候触发他工作,例如运行我们的测试,Xcode Bots 可以存放在服务器端。

我承认我自己并没有用过 Xcode Bots,但是我获得的所有反馈都告诉我这个东西并不好用。

总结下,如今缺乏好奇心的开发者和大公司,可以只使用苹果的技术,组建一整套运行在CI的单元测试和验收测试。用于工作基本上是足够了。

如果你正在阅读本文,你可能充满了好奇心,那么让我们继续看看开源社区有那些资源。

开源单元测试框架

iOS 和 OS X 开源社区充满了各种大牛和有趣的项目。在写本文的时候,在 pod 上一共有 8625 个开源项目。

这些单元测试的开源库主要都是行为描述风格(xSpec),一定程度上也反映了测试风格的一种趋势,这风格来自于 Ruby 测试库的 RSpec, 主要是测试类的行为,而不是枚举方法。

Kiwi

Kiwi 是一个全栈式的,XCTest的代替品,支持行为描述句式。实例代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
describe(@"Team", ^{
  context(@"when newly created", ^{
    it(@"has a name", ^{
      id team = [Team team];
      [[team.name should] equal:@"Black Hawks"];
    });
 
    it(@"has 11 players", ^{
      id team = [Team team];
      [[[team should] have:11] players];
    });
  });
});

Kiwi 测试用例通常非常容易阅读和理解代码所想要测试的内容,他就像一个好的说明文档。

Kiwi 集成了一些测试方法 期望(expectations), 模拟对象 (mock),桩程序 (stub),甚至还支持异步测试。

Specta

Specter 跟 Kiwi 非常像,但是它使用了不同的架构。Kiwi 是庞大的代替品 ,Specta 优势则体现在模块化与组件化。这个库关心的唯一事情是编写和运行 xSpec 风格的测试,然后用户可以根据使用期望(expectations), 匹配(matching),模拟对象(mock)和桩程序(stub)的情况来补充相应模块。

我个人更喜欢这个库的设计,轻量级,包含的多个模块可以被结合在一起。

这是 Specta 行为描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SpecBegin(Thing)
 
describe(@"Thing", ^{
  it(@"should do stuff", ^{
    // This is an example block. Place your assertions here.
  });
 
  it(@"should do some stuff asynchronously", ^{
    waitUntil(^(DoneCallback done) {
      // Async example blocks need to invoke done() callback.
      done();
    });
  });
});

注意 it 执行的时候 blocks 是空的。留给库的使用者来用他们喜欢的工具填写。

说到工具,这里有一个库名单,他们都可以与 Specta 和 Kiwi 配合使用:

  • Expecta a matcher framework, expect(foo).to.equal(bar).
  • OCHamcrest another matcher framework, assertThat(foo, equalTo(bar)).
  • OCMock a mocking framework.
  • OCMockito another mocking framework.
  • OHTTPStubs a library to stub network requests, with block based syntax to match URLs.
  • Nocilla another library to stub network requests, with a nice chain-able API, stubRequest(@”POST”, ).withHeaders(…).withBody(…).

Quick

Quick 是一个新的测试框架,也相当炫酷的一个。主要代码都是用 Swift 写的,非常适合用新的语言写测试组件。

1
2
3
4
5
6
7
8
9
10
11
import Quick
 
class ThingSpec: QuickSpec {
  override func spec() {
    describe("a ‘Thing‘") {
      it("should do stuff) {
        //
      }
    }
  }
}

多亏了 Swift 的语法和闭包,Quick 的行为描述看起来比 Kiwi 和 Specta 的可读性更强。

和 Qucik 一起的 Nimble 是一个 matcher 库,它允许用户进行简洁地表达,例如 expect(10) > 2

无论是 Objective-C 还是 Switf,单个庞大框架或是你喜欢的库组成的组件,开源社区提供了大量有价值的测试框架,特别是专注于写简洁测试的,感谢有表达句法(expressive syntax)。

验收测试的开源库

苹果提供的官方工具中单元测试框架和验收测试框架的质量对比也反应在开源社区中。可能是因为 XCTest 为开源单元测试框架们提供了一个坚实的基础,而 UIAutomation 没有,所以我们只能选择一些非常规的方法。

KIF

KIF,保持函数式(Keep It Functional),这是一个用 Objective-C 写的框架,让我们使用 XCTest 编写验收测试,然后在 Xcode 运行,方式和我们在单元测试做的一样。

KIF 使用私有的 API 来获得视图层级,然后让我们使用 accessibility 标签值来视图查询与交互。

1
2
3
4
5
6
7
8
- (void)testSuccessfulLogin {
  [tester enterText:@"user@example.com" intoViewWithAccessibilityLabel:@"Login User Name"];
  [tester enterText:@"thisismypassword" intoViewWithAccessibilityLabel:@"Login Password"];
  [tester tapViewWithAccessibilityLabel:@"Log In"];
 
  // Verify that the login succeeded
  [tester waitForTappableViewWithAccessibilityLabel:@"Welcome"];
}

KIF比较不好的地方在于作者响应时间较慢。这不是批判,毕竟开源世界一切都是免费的,但我们都要赚钱糊口,可以理解作者用在这些项目上的时间是有限的。但是当整个框架的基础都非常难以使用,那么他的稳定性一定很低。

Subliminal

Subliminal 是一个类似 KIF 的 Objective-C 框架,集成了 XCTest。和 KIF 不同的是,SUbliminal 是写在 UIAutomation 上层,旨在为开发者隐藏它的复杂性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (void)testLogInSucceedsWithUsernameAndPassword {
  SLTextField *usernameField = [SLTextField elementWithAccessibilityLabel:@"username field"];
  SLTextField *passwordField = [SLTextField elementWithAccessibilityLabel:@"password field" isSecure:YES];
  SLElement *submitButton = [SLElement elementWithAccessibilityLabel:@"Submit"];
  SLElement *loginSpinner = [SLElement elementWithAccessibilityLabel:@"Logging in..."];
 
  NSString *username = @"Jeff", *password = @"foo";
  [usernameField setText:username];
  [passwordField setText:password];
 
  [submitButton tap];
 
  // wait for the login spinner to disappear
  SLAssertTrueWithTimeout([loginSpinner isInvalidOrInvisible], 3.0, @"Log-in was not successful.");
 
  NSString *successMessage = [NSString stringWithFormat:@"Hello, %@!", username];
  SLAssertTrue([[SLElement elementWithAccessibilityLabel:successMessage] isValid],
  @"Log-in did not succeed.");
 
  // Check the internal state of the app.
  SLAssertTrue(SLAskAppYesNo(isUserLoggedIn), @"User is not logged in.")
}

Subliminal 声明它可以测试应用内购警告,甚至能使 app 进入睡眠。这听起来很牛,但事实是,在我写本文的时候,该库最近的一次代码提交是 2014年9月,而且还有 13 活跃的 pull request,这些都是不好的信号。

Calabash

目前我们所说到的工具中,Calabash 是最原始的一个。它是一个 Ruby 包,使用 Cucumber 编写 BDD 风格的验收测试,现在由 Xamarin 维护。Xamarin 是一个用 C# 写 iOS 和 Android 应用的框架。语言会不会有点多!

不像 KIF 和 Subliminal,Calabash 完全不集成在 Xcode 中。我创建示例使用的是 Vim 和 Rake。

我们书写 Cucumber 特性,执行每一步,然后使用命令行测试。为了它能够工作,需要在应用内嵌入一个 HTTP 服务器,用于查询和驱动 UI。

不用说,这可能是一个很大坑。

Cucumber/Calabash 测试代码差不多是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# rating_a_stand.feature
 
Feature: Rating a stand
  Scenario: Find and rate a stand from the list
    Given I am on the foodstand list
    Then I should see a "rating" button
    And I should not see "Dixie Burger & Gumbo Soup"
 
# steps.rb
 
Given(/^I am on the foodstand list$/) do
  wait_for_element_exists "view marked:‘Foodstand‘"
end
 
Given(/^I should see a "([^"]*)" button$/) do |button_title|
  wait_for_element_exists "button marked:‘#{button_title}‘"
end
 
Given(/^I should not see "([^"]*)"$/) do |view_label|
  wait_for_element_does_not_exists "view marked:‘#{view_label}‘
end

Calabash 好的地方在于它是一种陈述式的测试,管理层会喜欢如果他们会读到这些测试的话。而且它可以兼容两个平台。

另一方面,工具链并不是非常强大。测试运行相对较慢,需要在 Cucumer,Ruby,Objective 之间持续交换,消耗相当多的时间。

就像单元测试,开源库提供了不同的选择,用于改进你的工作流。唯一不同的是这些工具没那么成熟,社区没那么活跃。

持续集成平台

为我们的项目套上好的测试工具,其最后一步是拥有持续集成。在开发者机器上运行测试并不能保证代码不会出错,毕竟其他团队成员会对代码进行更改。有个人来不断运行测试会更加安全。

不用说,最好的 CI 是在云端进行。配置维护一套 Jenkins 需要大量的时间。

CI 的选择会更多。这里列出一些支持 iOS 项目的主要 CI 服务。

  • Travis CI
  • Ship.io
  • Sauce Labs
  • Bitrise
  • Testdroid

它们之间的区别主要是在价格,上手容易程度,以及如何配置。例如 Travis CI 使用 .travis.yml文件定义所有的步骤,而 Bitrise 则图形界面,每个步骤都用 block 展示,并且这block可以被添加到进程。

上面这个列表可能并不全面,我可能落了一些。希望这个对于有兴趣写测试和 CI 的人是一个好的开始。

2015年iOS测试现状


推荐阅读
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • andr ... [详细]
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • 本文详细分析了Hive在启动过程中遇到的权限拒绝错误,并提供了多种解决方案,包括调整文件权限、用户组设置以及环境变量配置等。 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 本文详细介绍了macOS系统的核心组件,包括如何管理其安全特性——系统完整性保护(SIP),并探讨了不同版本的更新亮点。对于使用macOS系统的用户来说,了解这些信息有助于更好地管理和优化系统性能。 ... [详细]
  • 高效解决应用崩溃问题!友盟新版错误分析工具全面升级
    友盟推出的最新版错误分析工具,专为移动开发者设计,提供强大的Crash收集与分析功能。该工具能够实时监控App运行状态,快速发现并修复错误,显著提升应用的稳定性和用户体验。 ... [详细]
  • VPX611是北京青翼科技推出的一款采用6U VPX架构的高性能数据存储板。该板卡搭载两片Xilinx Kintex-7系列FPGA作为主控单元,内置RAID控制器,支持多达8个mSATA盘,最大存储容量可达8TB,持续写入带宽高达3.2GB/s。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文详细介绍了Git分布式版本控制系统中远程仓库的概念和操作方法。通过具体案例,帮助读者更好地理解和掌握如何高效管理代码库。 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 本文介绍如何通过SSH协议使用Xshell远程连接到Ubuntu系统。为了实现这一目标,需要确保Ubuntu系统已安装并配置好SSH服务器,并保证网络连通性。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 本文深入探讨了 Java 编程语言的基础,特别是其跨平台特性和 JVM 的工作原理。通过介绍 Java 的发展历史和生态系统,帮助初学者理解如何编写并运行第一个 Java 程序。 ... [详细]
author-avatar
开心小笨笨猪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有