7

无法为特定场景设置单元测试。这是我正在尝试的:

  • 在 Xcode 4.5 中,我创建了一个简单的 OSX “命令行工具”应用程序项目(Foundation)。
    请注意,Xcode提供自动将单元测试添加到“命令行工具”项目的选项——因此请不要建议勾选勾选框;它不存在:-/

  • 在我的项目中,我创建了一个我想测试的简单示例类;例如“形状”。

  • 我按照 Apple 的Xcode Unit Testing Guide for Setting Up Unit-Testing in a Project 中的说明进行操作:

    • 我在我的项目中添加了一个单元测试目标,并且

    • 我编辑了“测试”方案以在新目标中运行测试。

  • 在测试项目的实现 (.m) 文件中,我Shape.h在方法中添加了导入和代码,setUp()以实例化形状并将其分配给实例变量。

那时,我决定看看事情是否会建立,以及默认测试是否会继续运行。但是,当我从菜单中选择Product...Test时,构建失败并出现以下错误:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_Shape", referenced from:
      objc-class-ref in ExampleTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解释这个错误不是问题。我觉得单元测试目标没有链接到包含 Shape 实现的二进制文件。但是,我(还)不了解 Xcode 单元测试和目标配置。所以:

为了使测试目标链接到命令行工具的结果输出,我需要做什么?我可以从单元测试目标链接到命令行可执行文件吗?Apple 的文档看起来特定于常规 OSX 应用程序 ( *.app) 和 iOS 应用程序,而这两者都不是。

我有我想在命令行工具设置中开发的业务逻辑类(开始),所以我想了解我需要做什么才能让单元测试目标在“命令行工具”中运行“项目类型。 谢谢!

(ps请注意,我对从命令行运行我的单元测试感兴趣——堆栈溢出已经提出了关于如何做到这一点的“类似”问题——而是“命令行工具”类型的项目上运行单元测试,并且仍然来自 Xcode。)

4

3 回答 3

13

我已经确定了一个我认为合适的解决方法,除了添加目标之外,它似乎没有明显的缺点。

简而言之:该解决方案涉及添加一个静态库目标,以利用 Xcode 围绕此类目标创建和运行单元测试代码的能力。然后命令行工具目标委托给静态库,其中定义了一个类似备用main()的函数,并由真正的main()入口点调用。命令行工具没有重要的代码,因此单元测试目标可以访问所有值得测试的东西。

以下是步骤:

  • 在一个空的 Xcode 中,从菜单中选择File...New Project

  • 在出现的对话框中,选择OS X...Application...Command Line Tool。出于本示例的目的,我假设它被命名为SampleCmd

创建基本命令行工具项目后:

  • 从菜单中选择File...New...Target

  • 在出现的对话框中,选择OS X...Framework & Library...Cocoa Library。出于本示例的目的,我假设它被命名为SampleCmdLogic

  • 选择类型Static,因此命令行工具将保持为独立的可执行文件。

  • 确保选中包含单元测试框。

创建静态库项目后:

  • main()函数从复制main.mSampleCmdLogic.m,替换@implementation块。(此文件将仅包含主入口点。可以为 Objective-C 类等添加其他文件。)  将函数重命名libMain()为.

  • SampleCmdLogic.h中,为 new 添加声明libMain(),替换@interface块:
    int libMain(int argc, const char * argv[]);

  • 在命令行工具中,在顶部main.m添加一个。#import "SampleCmdLogic.h"

  • 在命令行工具中,将真实函数main.m的全部内容更改为:main()
    return libMain(argc, argv);

代码现已准备就绪,但需要执行链接步骤:

  • 在 的项目设置中SampleCmd,在Build Phases下,展开Target Dependencies并添加 (+) SampleCmdLogic 作为依赖项。

  • 在项目设置中SampleCmd,在Build Phases下,展开Link Binary With Libraries并添加 (+)libSampleCmdLogic.a

现在一切都准备好了。当您更改为 SampleCmd 目标并从菜单中选择Product..Run时,构建应该会成功并按预期生成输出。当您更改为 SampleCmdLogic 目标并从菜单中选择Product...Test时,构建应该会成功并且单元测试将运行。报告的单个问题将是 Xcode 在SampleCmdLogicTests.m. 这是意料之中的。

从此时开始,继续将所有逻辑和相应的测试添加到 SampleCmdLogic 目标。SampleCmd 目标保持简单,仅提供命令行工具入口点。

于 2012-11-12T15:36:02.673 回答
3

通常有许多额外的步骤可以将测试目标添加到应用程序项目 - 特别是我在https://stackoverflow.com/a/12624873/246895中描述的 Bundle Loader 和 Test Host 的设置。

但是当我使用命令行工具进行测试并尝试运行测试时,它所做的只是运行该工具。对于应用程序,它会经历启动应用程序、将测试包注入正在运行的应用程序、然后执行测试的阶段。但是这些阶段不适用于命令行工具。

因此,您需要的不是注入的测试包,而是运行测试的第二个命令行工具。然后设置您的类,以便它们针对测试工具以及您的实际工具。gh-unitgoogle-toolbox-for-mac都遵循这个模型,所以我会尝试它们。

于 2012-11-02T17:23:01.283 回答
1

似乎最直接的问题只是Shape没有包含在新的测试目标中。尝试添加Shape.m到测试目标:

  1. 在 Project Navigator 中单击 Shape.m
  2. 打开实用程序视图(查看 -> 实用程序 -> 显示实用程序)
  3. 在 Utilities 视图的 Target Membership 部分中,确保您的应用程序测试目标都被选中。

我不知道这是否是您的设置问题的结束,但这似乎是您最直接的问题的可能候选者。

于 2012-11-12T07:14:25.567 回答