从命令行运行单元测试时的 SSL 连接问题

Posted

技术标签:

【中文标题】从命令行运行单元测试时的 SSL 连接问题【英文标题】:SSL Connections Issues when running Unit Tests from the command line 【发布时间】:2013-03-12 17:18:56 【问题描述】:

目标

我们的目标是在持续集成环境中执行我们的单元测试 (Jenkins)

(我认为每个问题都必须说明一个人想要达到的目标。也许这个问题实际上可以用一种非常不同的方式来解决)

更新:详细了解“您为什么要这样做?”

首先,我们正在讨论特定的、自主开发的硬件。我希望持续集成测试告诉我是否有人在不告诉所有开发人员的情况下更改了盒子的行为(是的,是的,我知道,这样的事情永远不会发生…)

其次,我们的一些(不是全部)连接使用默认无效的证书,因此我们有代码来检查证书的有效性(SecTrustEvaluate 等)。当然,理想情况下,我们的测试也会测试该代码。但这似乎太过分了。

第三:好吧,如果我能得到真正的交易,我为什么要嘲笑任何东西? IDE没有问题,为什么要命令行。

如果我想要可预测性,我会在所有测试中返回 YES ;)(我已经看到人们这样做)。不,我想知道代码是否真的和真的适用于我们的设备。这是某种变态的欲望吗?

问题已解决

从命令行运行测试听起来很简单,但是

xcodebuild -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO clean test

导致一个丑陋的错误:

unsupported build action 'test'

于是我在网上搜索,在Running OCUnit Tests from Command Line找到了这篇文章。

我遵循了所有步骤,并且可以像这样从命令行运行我的测试:

xcodebuild -scheme CITests -sdk iphonesimulator TEST_AFTER_BUILD=YES ONLY_ACTIVE_ARCH=NO clean build

剩下的问题

但是,现在到 SSL 服务器的任何 NSURLConnection 都会失败,因为“此服务器的证书无效。”。从命令行运行测试时,我听说过钥匙串问题,但这是真的吗?任何 SSL 连接都被拒绝?

复制

在https://github.com/below/SSLTestDemo 获取样品。打开它,然后使用 Xcode 自己的 Test ⌘U 命令运行示例测试。测试应该会成功。

现在在命令行上运行测试:

xcodebuild -scheme CITests -sdk iphonesimulator TEST_AFTER_BUILD=YES ONLY_ACTIVE_ARCH=NO clean build

由于“此服务器的证书无效”,测试失败。错误。

任何指针?

我做错了吗? 这是一个真正的错误吗? 如果有,是否有解决方法?

感谢任何输入!

【问题讨论】:

Mh 为什么要使用网络连接进行单元测试?通常,您会模拟此类事情以获得更可预测的结果并消除外部依赖关系。 见我上面的附录 回答你的问题,“当你可以拥有真实的东西时为什么要模拟”:你想消除变量。如果您在单元测试中实际连接到设备,则测试失败可能是由于代码提交以外的任何事情造成的。如设备已通电,未连接到网络。并不是说这些测试没有价值,但它们不是单元测试。 对。这些是集成测试,这是我们正在尝试做的。 作为单元测试运行时,您可能会遇到 SSL 主机检查问题。见quellish.tumblr.com/post/33284931593/… 【参考方案1】:

好吧,当我们在 Jenkins 下进行测试时,我只是没有检查证书。

由于在您的应用中存在阻止此类检查的代码是很危险的——毕竟,它可能不会在你发布之前被删除——你必须同时设置一个环境变量和一个编译器标志来激活它……

后脚本:

Apple 认为这是一个错误,rdar://problem/10406441

【讨论】:

【参考方案2】:

即使在 XCode(使用 XCode 4.5)中,我也遇到 SSL 连接问题

我的解决方案是在我的单元测试设置中切换 HTTPS 证书检查:

- (void)setUp

    // Set-up code here.
    [super setUp];

    NSURL *URL = [NSURL URLWithString:<#Your SSL Address#>];

    [NSURLRequest.class performSelector:NSSelectorFromString(@"setAllowsAnyHTTPSCertificate:forHost:")
                             withObject:NSNull.null  // Just need to pass non-nil here to appear as a BOOL YES, using the NSNull.null singleton is pretty safe
                             withObject:[URL host]];

我调用的深奥格式是因为这是一个私有方法,它拒绝使用最新的工具链进行编译。由于这仅在单元测试目标中使用,它不会影响生产代码,因此不会受到攻击、错误和 Apple AppStore 批准。 ymmv。

【讨论】:

您可以使用类扩展来允许从测试内部访问该方法。有关示例,请参阅我之前的评论。

以上是关于从命令行运行单元测试时的 SSL 连接问题的主要内容,如果未能解决你的问题,请参考以下文章

iphone sdk 4.3 从命令行运行单元测试

Xcode 命令行工具 (XCode 4.6) 从终端运行单元测试

如何在针对特定 Gradle 构建风格的同时从命令行运行单个单元测试方法

iPhone 命令行单元测试(和文件 I/O)

使用命令行的 Xcode 4 单元测试

从 1.5 迁移到 1.7 时的单元测试警告