在 Xcode 中进行自动化测试 (2/2)

欢迎回到我们的 Xcode 自动化测试入门系列!

在教程的第一部分, 你学到了如何将你的代码提交到 Git 上, 设置一个 Jenkins 持续集成服务器, 还有如何为你的应用添加单元测试。

在第二部分也是最后一部分中, 你将学到关于单元测试更多的东西, 还有如何将你的构建打包并上传到 TestFlight 中!

创建一个单元测试类

现在,让我们添加一个简单的单元测试类, 用来测试 WowUtils 类。
WowUtils 从 Web 服务的 JSON 数据中查询关于角色的类型, 种族的字符串。

最好对你们一个想要测试的类都创建一个单元测试。 Xcode 有一个 Objective-C 测试用例类 的模板。

在 Xcode 的 project navigator 中, 右键点击 GuildBrowserLogicTests 分组, 选择 New FileCocoa TouchObjective-C test case class, 点击 Next,输入 WowUtilsTests 作为类名, 再次点击 Next, 确保只有GuildBrowserLogicTests target 是选中的, 并且点击 Create。

现在你有了一个 测试套件, 可以在里面添加一些 测试用例 了。 让我们创建你的第一个测试用例。 这个测试用例,用来确保你在查找每个角色的类的时候能得到正确的响应。这里是你要测试 WowUtils.h 类的方法:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">+</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSString</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>classFromCharacterType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>CharacterClassType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>type;  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">+</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSString</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>raceFromRaceType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>CharacterRaceType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>type;  
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">+</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSString</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>qualityFromQualityType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>ItemQuality<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>quality;  

注意:
这些方法被期望从暴雪的web服务中得到正确的名称。
在下面你可以看到 WowUtils 的输出(Chrome 是检测来自 web 服务的 JSON 输出的好工具):

将 WowUtilsTests.m 的内容替换成:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#import "WowUtilsTests.h"</span>  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#import "WowUtils.h"</span>  
  3.    
  4. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">@implementation</span> WowUtilsTests  
  5.    
  6. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 1</em></span>  
  7. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testCharacterClassNameLookup  
  8. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  9.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 2</em></span>  
  10.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Warrior"</span>,  
  11.                          <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils classFromCharacterType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">1</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>,  
  12.                          <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"ClassType should be Warrior"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  13.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 3</em></span>  
  14.     STAssertFalse<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Mage"</span> isEqualToString<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils classFromCharacterType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">2</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>,  
  15.                   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  16.    
  17.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 4</em></span>  
  18.     STAssertTrue<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Paladin"</span> isEqualToString<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils classFromCharacterType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">2</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>,  
  19.                  <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  20.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// add the rest as an exercise</em></span>  
  21. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  22.    
  23. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testRaceTypeLookup  
  24. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  25.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Human"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils raceFromRaceType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">1</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  26.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Orc"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils raceFromRaceType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">2</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  27.     STAssertFalse<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Night Elf"</span> isEqualToString<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils raceFromRaceType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">45</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  28.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// add the rest as an exercise</em></span>  
  29. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  30.    
  31. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testQualityLookup  
  32. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  33.     STAssertEquals<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Grey"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils qualityFromQualityType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">1</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  34.     STAssertFalse<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Purple"</span> isEqualToString<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>WoWUtils qualityFromQualityType<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">10</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  35.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// add the rest as an exercise</em></span>  
  36. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  37.    
  38. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">@end</span>  

让我们一点一点的看它。

  1. 就像是刚开始说的, 所有的测试用例都以 test 开头。
  2. 我们的期望是 WowUtils 类将会给你正确的类名,ID。 你通过 STAssert* 宏来验证这个期望。这里你用到了 STAssertEqualObjects 宏。
    期望的结果, “Warrior”, 将会和 WowUtils 方法的结果进行比较;如果测试失败了, 你将会记录消息“ClassType should be Warrior”
  3. 将 “失败测试” 包含在测试用例中是很好的。这是一个期望结果失败的测试。
    再说一次, 你使用 SenTestingKit 中的其中一个断言宏 – 这次是 STAssertFalse。

    期望的结果, “Mage” 会和 WowUtils 方法的结果进行比较;如果测试失败了, 你将使用默认的消息, 因为你在这个例子中传入的是 nil。

  4. 最后, 你使用了另外一个测试宏的例子。
注意:
关于测试宏的完整列表, 可以看一下苹果开发者库中的单元测试结果宏参考(http://bit.ly/Tsi9ES)。
For a complete list of the testing macros,

现在你可以运行包含一个测试用例的测试套件了。
进入 ProductTest (⌘-U).

你看到了一个编译错误!

因为你添加了一个新的 target, 你需要让它知道哪些类需要测试。 每个 target 都有它自己可用的源文件列表。 你需要手工的添加这些源文件, 因为你运行的逻辑测试 target 没有包含相应的源文件。

  1. 切换到 project navigator – 如果它没有打开, 使用 ViewNavigatorsShow Project Navigator menu item (⌘-1).
  2. 点击项目的根目录来打开 Project 和 Targets 编辑器。
  3. 在 Xcode 的主编辑面板中,选择 Build Phases 标签。
  4. 在 TARGETS 部分点击 GuildBrowserLogicTests target。 你应该看到这个:

  5. 展开 Compile Sources 部分的三角箭头, 并且点击 + 按钮。
    在弹出窗口中, 选择这些类 Character.m, Guild.m, Item.m, 和 WowUtils.m. 然后点击 Add.

  6. 现在将应用的 target 作为一个依赖项, 这样我们在测试 target 运行前会进行一次构建。展开 Target Dependencies 部分的三角箭头, 点击 + 按钮, 选择 GuildBrowser 应用 target 并且点击 Add

当这几步完成后, 你将会看到如下内容:

现在运行 ProductTest (⌘-U) 并且测试应该成功了。 你可以切换到 Log Navigator (go to ViewNavigatorsShow Log Navigator (⌘-7)), 就可以看到所有测试的输出了。

当你点击左边栏最后一次构建时, 你将会看到这些:

确保把你最后的修改 commit 并且 push 到 Github 上。

通过本地的 JSON 数据来测试一个类。

让我们看一下 Character 类, 并且为它添加测试套件。 理想情况下, 你应该在开发这个类的时候就添加这些测试。

如果你想测试从本地数据来创建你的 Character 类, 那又怎么办呢?
你会怎么做呢? 如果你想将这些数据共享给其他测试用例呢?

目前为止, 你没有对你的单元测试使用两个特殊的方法: setUp 和 tearDown. 每次你运行单元测试时, 每个测试都独立的被调用。 在每个测试用例运行之前, setUp 方法会被调用, 之后, tearDown 方法会被调用。 这也是你怎样在每个测试用例之间共享代码的方法。

当构建一个应用,需要从服务器获取数据时, 我发现通过使用从服务端获取的有效数据来创建测试非常有帮助。通常对于一个项目来说, 你仅负责客户端的部分, 并且等待另一个开发者的服务端。你们可以商量好一种格式, 然后将这些数据模拟到一个 JSON 文件中。对于这个应用, 我下载了一些角色和公会的数据, 用于创建模型类的测试, 这样我可以先不考虑网络通讯的代码。

首先, 添加你的测试数据。 解压这个 AutoTestData.zip 文件, 把 result 目录拖动到你的 Xcode 项目中。 确保 Copy items into destination group’s folder (if needed) 是选中的,Create groups for any added folders 是选中的, 还有 GuildBrowserLogicTests 也是选中的,然后点击 Finish 按钮。

为你的 Character 添加一个 Objective-C 测试用例类。
在 Xcode project navigator 中, 右键点击 GuildBrowserLogicTests 分组, 选择 New FileCocoa TouchObjective-C test case class
点击 Next, 输入 CharacterTests 作为类名,
再次点击 Next,确保只有 GuildBrowserLogicTests target 是选中的, 然后点击 Create。

将 CharacterTests.m 的内容替换成:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#import "CharacterTests.h"</span>  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#import "Character.h"</span>  
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#import "Item.h"</span>  
  4.    
  5. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">@implementation</span> CharacterTests  
  6. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  7.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 1</em></span>  
  8.     <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSDictionary</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>_characterDetailJson;  
  9. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  10.    
  11. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 2</em></span>  
  12. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>setUp  
  13. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  14.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 3</em></span>  
  15.     <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSURL</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>dataServiceURL <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSBundle</span></a> bundleForClass<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>self.class<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>  
  16.                              URLForResource<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"character"</span> withExtension<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"json"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  17.    
  18.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 4</em></span>  
  19.     <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSData</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>sampleData <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSData</span></a> dataWithContentsOfURL<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>dataServiceURL<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  20.     <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/" style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,104,55); text-decoration:initial"><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(64,0,128)">NSError</span></a> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>error;  
  21.    
  22.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 5</em></span>  
  23.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">id</span> json <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>NSJSONSerialization JSONObjectWithData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>sampleData  
  24.                                               options<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>kNilOptions  
  25.                                                 error<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:&</span>error<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  26.     STAssertNotNil<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>json, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"invalid test data"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  27.    
  28.    
  29.     _characterDetailJson <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> json;  
  30. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  31.    
  32. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>tearDown  
  33. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  34.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 6</em></span>  
  35.     _characterDetailJson <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span>;  
  36. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  37.    
  38. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">@end</span>  

慢慢讲起 :]

  1. 记住, 测试类可以拥有实例变量, 就像是其他的 Objective-C 类一样。 你在这里创建了 _characterDetailJson 实例变量用来存储你的示例 JSON 数据。
  2. 记住 setUp 方法会在每一个测试用例之前调用。这非常有用, 因为你仅需要加载一次, 然后可以在每个测试用例中维护它。
  3. 为了正确的加载数据文件,记住这个作为测试 bundle 运行。 你需要将 self.class 发送给 NSBundle 方法来查找 bundle 中的资源。
  4. 从加载的资源中,创建 NSData。
  5. 现在,创建 JSON 数据, 并且将它存放在你的实例变量中。
  6. 记住, tearDown 将会在每个测试用例结束时调用。 这是一个执行清理操作的好地方。

通过运行 ProductTest (⌘-U) 来确保一切都正确的加载。 好了, 现在你的类可以在开始时,加载一些测试数据了。

在 tearDown 后面, 添加如下代码:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 1</em></span>  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testCreateCharacterFromDetailJson  
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  4.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 2</em></span>  
  5.     Character <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>testGuy1 <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Character alloc<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span> initWithCharacterDetailData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>_characterDetailJson<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  6.     STAssertNotNil<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>testGuy1, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Could not create character from detail json"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  7.    
  8.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 3</em></span>  
  9.     Character <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>testGuy2 <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Character alloc<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span> initWithCharacterDetailData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  10.     STAssertNotNil<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>testGuy2, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Could not create character from nil data"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  11. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  

讲解一下!

  1. 这里你为 Character 的初始化方法创建了一个测试用例,从 JSON 数据中得到一个 NSDictionary, 并且设置好属性。这看起来不重要, 但是记住, 当你开发应用的饿时候, 最好添加这个测试, 尤其是你在增量的开发这个类的时候。
  2. 这里你仅验证了 initWithCharacterDetailData 方法会返回一些东西, 使用了另外一个 STAssert 宏, 来确保它不是 nil。
  3. 这是一个反向测试, 验证了即便你传入一个 nil 的 NSDictionary 数据, 你仍然能得到一个 Character。

运行 ProductTest (⌘-U) 确保你的测试仍然能够通过!

在 CharacterTests.m 中的 testCreateCharacterFromDetailJson 方法后面, 添加如下内容:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 1</em></span>  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testCreateCharacterFromDetailJsonProps  
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  4.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.thumbnail, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"borean-tundra/171/40508075-avatar.jpg"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"thumbnail url is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  5.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.name, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Hagrel"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  6.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.battleGroup, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Emberstorm"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"battlegroup is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  7.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.realm, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Borean Tundra"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"realm is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  8.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.achievementPoints, @<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">3130</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"achievement points is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  9.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.level,@<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">85</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"level is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  10.    
  11.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.classType, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Warrior"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"class type is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  12.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.race, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Human"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"race is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  13.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.gender, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Male"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"gener is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  14.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.averageItemLevel, @<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">379</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"avg item level is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  15.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.averageItemLevelEquipped, @<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">355</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"avg item level is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  16. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  
  17.    
  18. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>// 2</em></span>  
  19. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">void</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>testCreateCharacterFromDetailJsonValidateItems  
  20. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  21.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.neckItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Stoneheart Choker"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  22.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.wristItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Vicious Pyrium Bracers"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  23.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.waistItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Girdle of the Queen's Champion"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  24.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.handsItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Time Strand Gauntlets"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  25.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.shoulderItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Temporal Pauldrons"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  26.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.chestItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Ruthless Gladiator's Plate Chestpiece"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  27.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.fingerItem1.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Thrall's Gratitude"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  28.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.fingerItem2.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Breathstealer Band"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  29.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.shirtItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Black Swashbuckler's Shirt"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  30.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.tabardItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Tabard of the Wildhammer Clan"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"nname is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  31.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.headItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Vicious Pyrium Helm"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  32.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.backItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Cloak of the Royal Protector"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  33.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.legsItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Bloodhoof Legguards"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  34.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.feetItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Treads of the Past"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  35.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.mainHandItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Axe of the Tauren Chieftains"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  36.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.offHandItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">nil</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"offhand should be nil"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  37.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.trinketItem1.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Rosary of Light"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  38.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.trinketItem2.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Bone-Link Fetish"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  39.     STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>_testGuy.rangedItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Ironfeather Longbow"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"neck name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  
  40. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>  

你需要确保这些属性正确的和你初始加载的 JSON 数据中的保持一致。 简单的讲解一下:

  1. 这个测试了主屏幕 Character 单元测中显示的信息。
  2. 这个测试了当你从主屏幕点击 Character 单元格时显示在 CharacterDetailViewController 中的信息。

为了更有趣一些,”强制自己忘记” 去运行 ProductTest (⌘-U), 并且 commit 和 push 你的修改。当你更新你的 Jenkins 作业脚本来包含测试时,你将会看到,你的朋友 Jenkins 将会去查找。

完成你的 Jenkins 作业

首先, 确保提交了你的所有修改, 并且将他们 push 到 你在 Github 上的 origin/master 分支中。

作为一个提醒, 你将要进行下面这些操作:

  1. 进入 FileSource ControlCommit (⌥⌘-C), 然后在在接下来的屏幕中, 输入一个类似于 “added test target” 的提交消息, 然后点击 Commit
  2. 将本地的 master 分支 push 到远程的 origin/master 分支中。进入 FileSource ControlPush 然后点击 Push

现在再次编辑你的 Jenkins 作业,将你刚刚设置好的测试用例包含进来。 进入 Jenkins DashboardGuildBrowser jobConfigure。 在 Build 部分, 将现有的代码替换成这个:

  1. export DEVELOPER_DIR<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=/</span>Applications<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode.app<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Contents<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>  
  2.    
  3. xcodebuild <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>target GuildBrowserLogicTests   
  4. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>sdk iphonesimulator   
  5. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>configuration Debug   
  6. TEST_AFTER_BUILD<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">YES</span>   
  7. clean build  

点击 Save 然后点击 Build Now.

恩, 运行! 你打断了构建, Chuck Norris 将会找到你! 这很严重, 没有人能够逃脱。 :]

那么,发生了什么呢? 你可清理掉 Mr. Norris 的雷达用来追踪你的构建日志输出, 或者… 你可以设置 Jenkins,来给你提供一些结果报告!我不了解你,但如果是我在这个雷达上, 我希望尽快把它关上! 你应该也接到了一个电子邮件, 告诉你构建失败了。 让我们获取一些报告吧, 开始!

获取单元测试报告

每次构建之后那些日志输出非常乏味,如果一个方便的报告,可以让你看到哪些测试通过了, 哪些测试失败了, 将会非常有用。

好吧, 恰好有一个脚本可以做这件事! Christian Hedin 写了一个非常棒的 Ruby 脚本, 用来将 OCUnit 的输出转换成 JUnit 风格的报告。你可以在 GitHub 上找到它 https://github.com/ciryon/OCUnit2JUnit

这个 Ruby 脚本的一个拷贝已经在这章的资源目录里面了。 赶快, 记住你在谁的雷达上面!

将 ocunit2junit.rb 文件拷贝到一个 Jenkins 可以访问到的地方 – 我把我自己的放到了 /usr/local/bin 中。 记录一下这个位置,在更新构建作业的时候使用它。

在 GuildBrowser Jenkins job, 将 shell 脚本更新成如下内容:

  1. export DEVELOPER_DIR<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=/</span>Applications<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode.app<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Contents<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>  
  2.    
  3. xcodebuild <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>target GuildBrowserLogicTests   
  4. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>sdk iphonesimulator   
  5. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>configuration Debug   
  6. TEST_AFTER_BUILD<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">YES</span>   
  7. clean build | <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>local<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>ocunit2junit.rb  

唯一的不同之处在最后一行, 这个构建的输出内容将通过管道传送到 Ruby 脚本中进行处理。

现在你需要添加另一个 Post-Build Action 脚本到你的作业中,用来捕获这些报告。在设置界面的最下面, 点击 Add post-build action 按钮, 然后选择 Publish JUnit test result report.

在 Test report XMLs 文本框中输入 test-reports/*.xml

点击 Save 然后点击 Build Now。 档这个作业完成后, 你进入 GuildBrowser 作业的主项目区域, 你应该看到 Latest Test Result 链接。 进入这个链接。

Now it’s really obvious what has angered “He who must not be named.”

CharacterTests 类找到了一个 bug。 让我们进一步的检查, 点击测试名称上面的链接:

  1. Error Message  
  2.    
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Vicious Pyrium Bracers"</span> should be equal to <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Girdle of the Queen"</span>s Champion<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">" name is wrong  
  4.    
  5. Stacktrace  
  6.    
  7. /Users/charlie/.jenkins/workspace/GuildBrowser/GuildBrowserLogicTests/testclasses/CharacterTests.m:58</span>  

好吧, 让我们去看一下测试代码。 首先看一下 CharacterTests.m 的 第 76 行:

  1. STAssertEqualObjects<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">(</span>hagrel.waistItem.name,<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Girdle of the Queen's Champion"</span>, <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name is wrong"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">)</span>;  

非常有趣! 打开 character.json 文件看一下; 或许是你的数据有问题, 但确定不是代码!

注意:
当操作 JSON 的时候, 我非常推荐通过这个非常棒的网站 jsonlint.com 来验证你的测试数据和其他任何类型的 JSON。它不仅能验证 JSON , 还能格式化它们。

记住 character.json 表示了从暴雪服务器返回的数据。你将会找到这个片段:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  2.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"thumbnail"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"borean-tundra/171/40508075-avatar.jpg"</span>,  
  3.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"class"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">1</span>,  
  4.     <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"items"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  5.         …  
  6.         <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"wrist"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  7.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"icon"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"inv_bracer_plate_dungeonplate_c_04"</span>,  
  8.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"tooltipParams"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  9.                 <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"extraSocket"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(166,19,144)">true</span>,  
  10.                 <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"enchant"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">4089</span>  
  11.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>,  
  12.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Vicious Pyrium Bracers"</span>,  
  13.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"id"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">75124</span>,  
  14.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"quality"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">3</span>  
  15.         <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>,  
  16.         <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"waist"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  17.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"icon"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"inv_belt_plate_dungeonplate_c_06"</span>,  
  18.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"tooltipParams"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">{</span>  
  19.                 <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"gem0"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">52231</span>  
  20.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>,  
  21.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"name"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Girdle of the Queen's Champion"</span>,  
  22.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"id"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">72832</span>,  
  23.             <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"quality"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">4</span>  
  24.         <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">}</span>,  
  25. …  

恩, 你的测试找到了 “Vicious Pyrium Bracers”, wrist 这项的名称, 但是要找的是 “Girdle of the Queen’s Champion”, 作为 waist 的名称。 它更像是一个 bug 了!

你可以看一下你的测试 CharacterTest.m

  1. Character <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>hagrel <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Character alloc<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span> initWithCharacterDetailData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>characterDetailJson<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  

打开 Character.m看一下 initWithCharacterDetailData:。 你能找到 bug 吗?

  1. _wristItem <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Item initWithData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>data<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"items"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"wrist"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  
  2. _waistItem <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Item initWithData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>data<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"items"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"wrist"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  

你对 waistItem 使用了错误的 key。 修改最后一行代码,来修复这个 bug:

  1. _waistItem <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span>Item initWithData<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">:</span>data<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"items"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">[</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"waist"</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">]</span>;  

好了, 提交你的修改,并 push 到 GitHub 中。进入 Jenkins 项目, 并且点击 Build Now. 。

测试结果: 没有失败! 如释重负!

点击 Latest Test Resultroot 深入到报告中, 你将看到所有这些测试都运行了。 通过进一步研究 CharacterTests, 你可以看到, 你修复了这个问题(仔细看一下第三行的状态 :]):

轮询更改

让我们设置 Jenkins 项目, 每 10 分钟检测一下修改, 如果它找到了修改, 就会运行构建。
进入 Jenkins DashboardGuildBrowser jobConfigure 再次修改你的 Jenkins 作业。
在 Build Triggers 部分, 选择 Poll SCM 复选框, 在 schedule 文本框中, 输入:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*/</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">10</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">*</span>  

点击保存。 现在一旦有新的代码提交到 origin/master 仓库中, 构建就会开始。当然, 你仍然可以像使用 Build Now 按钮那样手动的进行构建。

自动打包

让我们更新一下构建脚本, 在每次成功完成测试后打包你的应用。
再次编辑你的 Jenkins 作业, 你猜到了, 进入 Jenkins DashboardGuildBrowser jobConfigure.

你将会添加另外一个 shell 步骤, 将会在测试脚本执行完之后再执行。
在 Build 部分, 点击 Add build step, 并且在下拉框中选择 Execute shell

输入如下内容,将 CODE_SIGN_IDENTITY 替换成你自己的发布证书的名称:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># tests passed archive app</span>  
  2.    
  3. export DEVELOPER_DIR<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=/</span>Applications<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode.app<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Contents<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer  
  4.    
  5. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>xcrun xcodebuild <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>scheme GuildBrowser clean archive   
  6. CODE_SIGN_IDENTITY<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"iPhone Distribution: Charles Fulton"</span>  

你的构建部分看起来应该是这样的:

如果你保存了修改, 并且再次用 Jenkins 进行构建, 你将会在 Xcode 的 organizer 中看到最后打好的包。在 Xcode 中, 打开 WindowOrganizer 并且切换到 Archives 标签, 然后你将会在左边的列表中看到 GuildBrowser 项目。

当你点击这个项目时, 你将会看到你所有打包好的构建。这非常棒,因为现在你知道了你在构建并且测试同一个包, 这个包将会被提交到 AppStore 中!

注意: 如果打包失败了, 你将不会在 Xcode Organizer 中看到它, 你也不会在 Jenkins 中看到打包失败的消息。 你需要去看一下构建日志来确定打包是否真正成功了。

通常, 打包失败的原因是 CODE_SIGN_IDENTITY 没有正确设置引起的, 或者它没有匹配到项目的 Bundle ID。所以, 如果你遇到任何打包失败的情况,这些情况需要检查一下。 一个解决方案是设置 CODE_SIGN_IDENTITY 为 iPhone Distribution, 因为这会匹配默认的发布配置。

还要记住, 如果你对项目进行任何修改来修复上面的问题, 你需要将他们提交并且 push 到 GitHub 上面。 否则, Jenkins 不会在下次构建中找到你的这些修改。:)

接下来, 你将会把打好的包发送到 TestFlight 中, 并且在 Jenkins 对这些 artifact(Jenkins 对于构建结果的术语) 保持跟踪。

将打好的包发布到 TestFlight

iOS 开发社区最好的一件事就是, 在过去几年中, 出现了一大批非常棒的框架和服务。

在以前, 将 beta 构建提交给测试人员是一件很麻烦的事情。你需要将你的 IPA 文件通过 email 发送给他们, 将他们拖进 iTunes, 然后连接他们的设备, 并且通过 iTunes 把他们同步进去。你还需要给他们发送 email 来询问他们设备的 UDID, 写下他们并且创建新的 provisioning profile, 然后创建新的构建。 始终确定那个设备属于哪个用户, 他们运行的是哪个 iOS 版本, 简直就是一场噩梦。

使用 TestFlight 吧! 这个网站能让你轻松的发布并测试 beta 版本。 在 TestFlight 之前, 唯一将发布构建提交给 beta 测试人员的方式就是使用 ad hoc 构建。ad hoc 构建仍然有用, 因为 TestFlight 也是基于 ad hoc 机制的, 但是它能让发布和管理这些构建更加简单。

Testflight 还能让你在你的应用中设置他们的 TestFlight SDK, 来进行崩溃日志分析, 使用情况分析, 还有更多!

我们将会集中 TestFlight 提供的于自动上传并且发布功能。

PackageApplication

这里是一个非常小的 Perl 脚本, 包含在 Xcode.app bundle 中, 你可以看一眼:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Applications<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode.app<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Contents<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Platforms<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>iPhoneOS.platform<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>PackageApplication  

这个工具可以让你对最后一次打包的构建进行如下操作。 你将要修改你的 Jenkins 打包步骤:

  • 创建 GuildBrowser.app bundle;
  • 嵌入你的 ad hoc provisioning profile;
  • 使用你的发布证书进行签名。

为了确保你做一切就绪, 从 iOS Provisioning Portal 中下载最近的 ad hoc provisioning profile, 并且将它放到你项目的顶级目录中。

下载完它之后, 你的项目看起来应该和下面图片中的一样。
注意, 我的 ad hoc provisioning profile 名叫 Charles_Fulton_All_Ad_Hoc.mobileprovision:

注意: 你的 .mobileprovision 在任何地方都可以被找到. 你只需要保证提供它的绝对路径, 而不是相对路径。 例如:

~/Library/MobileDevice/Provisioning Profiles/

必须是:

/Users/charlie/Library/MobileDevice/Provisioning Profiles/

我喜欢将我自己的放到 Git 中, 这样当有新的设备添加进来后, 我只需要签入新的 new provisioning profile 就可以了。然后我就可以在 Jenkins 中进行一次手动构建了。

确保添加完这个文件后 commit 并且 push 到 GitHub,这样 Jenkins 才能看到他们。

如果你使用 Xcode 提交到 Git 的话, 那么要注意将 mobile provisioning profile 添加到 Xcode 项目中。否则, 你不能将它提交到 Git 中。 如果你使用的是命令行或者单独的 Git 客户端, 那么这个问题就没有了。

让我们再次编辑一下你的 Jenkins 作业。 进入 Jenkins DashboardGuildBrowser jobConfigure。 添加一个新的 Build step execute shell:

  1. export DEVELOPER_DIR<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=/</span>Applications<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode.app<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Contents<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer  
  2.    
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#</span>  
  4. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># Setup </span>  
  5. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># </span>  
  6. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># 1 </span>  
  7. PROJECT<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"GuildBrowser"</span>  
  8. SIGNING_IDENTITY<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"iPhone Distribution: Charles Fulton"</span>  
  9. PROVISIONING_PROFILE<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${WORKSPACE}/Charles_Fulton_All_Ad_Hoc.mobileprovision"</span>  
  10.    
  11. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># 2 </span>  
  12. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># this is the latest archive from previous build step</span>  
  13. ARCHIVE<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"$(ls -dt ~/Library/Developer/Xcode/Archives/*/${PROJECT}*.xcarchive|head -1)"</span>  
  14. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># 3</span>  
  15. IPA_DIR<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${WORKSPACE}"</span>  
  16. DSYM<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${ARCHIVE}/dSYMs/${PROJECT}.app.dSYM"</span>  
  17. APP<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${ARCHIVE}/Products/Applications/${PROJECT}.app"</span>  
  18.    
  19.    
  20. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># </span>  
  21. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># PackageApplication</span>  
  22. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#</span>  
  23.    
  24. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># package up the latest archived build</span>  
  25. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>rm <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>f <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.ipa"</span>  
  26.    
  27. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># 4</span>  
  28. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>xcrun <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>sdk iphoneos PackageApplication   
  29. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>o <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.ipa"</span>   
  30. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>verbose <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${APP}"</span>   
  31. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>sign <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${SIGNING_IDENTITY}"</span>   
  32. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">--</span>embed <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${PROVISIONING_PROFILE}"</span>  
  33.    
  34. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># zip and ship</span>  
  35. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>rm <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>f <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.dSYM.zip"</span>  
  36.    
  37. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># 5</span>  
  38. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>zip <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>r <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.dSYM.zip"</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${DSYM}"</span>  

这个构建脚本有很多内容, 你知道都是什么意思。

详细讲解一下!

  1. 这些是用来设置,当你创建 IPA 文件的时候要使用哪些证书和 provisioning profile。 你应该修改SIGNING_IDENTITY 和 PROVISIONING_PROFILE 来使用你的 ad hoc 发布设置。
  2. 这个 shell 小技巧用来找到最后一个打包的位置。 想进一步的了解这个, 打开命令行并且运行这个命令:

    1. ls <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>dt ~<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Library<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Archives<span style="margin:0px; padding:0px; border:0px; outline:0px; font-family:inherit; vertical-align:baseline; color:rgb(17,116,10)"><em>/*/GuildBrowser*.xcarchive|head -1</em></span>  

    你应该看到输出是这样的:

    1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Users<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>charlie<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Library<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Developer<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Xcode<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>Archives<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">2012</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>08<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">27</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>GuildBrowser <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">8</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">27</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">12</span> <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(36,0,217)">10.37</span> AM.xcarchive<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>  
  3. 你现在可以使用 ARCHIVE 变量来创建 APP 和 DSYM 变量,保存发送到 PackageApplication 的绝对路径。 试试这个命令:

     

    1. ls –l <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"/Users/charlie/Library/Developer/Xcode/Archives/2012-08-27/GuildBrowser 8-27-12 10.37 AM.xcarchive/Products/Applications/GuildBrowser.app"</span>  
  4. 这里你调用了 PackageApplication 脚本。 注意一下 Jenkins 给你提供了一些非常好的环境变量在 $WORKSPACE 中。 $WORKSPACE 变量可以让你得到 Jenkins 作业的绝对路径。 你现在可以在 Jenkins 中构建出要发送到用户手中的包了。
  5. 从包中压缩 dSYMs。dSYMs 用来记录崩溃日志, 这样你可以找出是哪个源文件,方法,代码行,等等。而不是得到一些内存地址,这种对你毫无意义的信息。

在保存和构建更新后的脚本之前, 让我们添加一个步骤, 用来对所有成功创建的 .app 和 dSYMs 打包。

进入 Post-build Actions 部分, 从 Add post-build action 菜单中选择 Archive the artifacts

在 files to archive 文本框中输入 *.ipa, *.dSYM.zip 。

点击 Save 然后选择 Build Now。 当构建成功后, 你会看到这个:

如果这时失败了, 通常是因为签名信息不正确,或者是因为在项目的根目录里面找不到 ad hoc provisioning profile。看一下构建日志来找出问题发生在哪。

任务完成

让我们把打好的包发送到 TestFlight 并且通知你的用户有新的构建。

注意: 这部分假设你已经有了一个 TestFlight (testflightapp.com) 账号。 你将要用到你的 TestFlight team 和 API token。

你可以从这里得到你的 API token: https://testflightapp.com/account/#api

进入 TestFlight 后, 你可以点击 team info 按钮来得到你的 team token。

进入 Jenkins DashboardGuildBrowser jobConfigure., 编辑你的 Jenkins 作业。 你将要编辑你在前一步中添加的脚本。

添加这些代码,在 DEVELOP_DIR 这行的后面, 填入你自己的 TestFlight 信息:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># testflight stuff</span>  
  2. API_TOKEN<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><YOUR API TOKEN>  
  3. TEAM_TOKEN<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><YOUR TEAM TOKEN>  

将这些添加到现有脚本的后面:

  1. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#</span>  
  2. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)"># Send to TestFlight</span>  
  3. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(110,55,26)">#</span>  
  4. <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>usr<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>bin<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">/</span>curl <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"http://testflightapp.com/api/builds.json"</span>   
  5.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F file<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.ipa"</span>   
  6.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F dsym<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">@</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${IPA_DIR}/${PROJECT}.dSYM.zip"</span>   
  7.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F api_token<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${API_TOKEN}"</span>   
  8.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F team_token<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"${TEAM_TOKEN}"</span>   
  9.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F notes<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Build ${BUILD_NUMBER} uploaded automatically from Xcode. Tested by Chuck Norris"</span>   
  10.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F notify<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span>True   
  11.   <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">-</span>F distribution_lists<span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(0,34,0)">=</span><span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">'all'</span>  
  12.    
  13. echo <span style="margin:0px; padding:0px; border:0px; outline:0px; font-style:inherit; font-family:inherit; vertical-align:baseline; color:rgb(191,29,26)">"Successfully sent to TestFlight"</span>  

点击 Save 并且进行另外一次 Build Now.

现在,当构建作业完成后, 你的构建应该已经发送到 TestFlight 了!你的用户应该接收到了一封新的电子邮件, 告诉他们有新的构建可用。这样可以让他们马上从 email 中安装你的应用, 并且开始测试!

接下来去哪?

你现在应该学会了自动构建, 测试,并且发布你的 iOS 应用!

让我重新提示一下你在这章所做的事:

  • 首先, 你学到了如何设置一个远程的 GitHub 仓库, 让你能够分享并测试你的代码。
  • 然后, 你了解了使用 Jenkins 进行持续集成,并且一步步的创建了一个非常好的构建脚本, 首先构建, 然后测试, 最后将你的包发送到 Testflight。
  • 你还看到了如何使用 “自底向上” 的单元测试来测试你的代码。如果你对 iOS 单元测试感兴趣, 我强烈推荐 Graham Lee 的这本书 Test-Driven iOS Development 。我还鼓励大家给苹果提一些建议, 能够简单的通过脚本运行应用的单元测试, 而不是通过 Hack!

如果你喜欢这个教程,并且想了解更多, 看一看这本新书 iOS 6 by Tutorials,里面包含了, 通过创建一个非常酷的测试机器人,对同样的应用进行 “自顶向下” 的单元测试。这个机器人将使用 instruments 和 UI Automation 来在 GuildBrowser 应用中驱动一些 UI 交互。

posted @ 2016-01-21 15:07  想吃天鹅肉的井底之蛙  阅读(566)  评论(0编辑  收藏  举报