何时需要将应用程序源包含在测试目标中?

2024-01-25

在一个新项目中我有这个简单的测试

#import <XCTest/XCTest.h>
#import "ViewController.h"

@interface ViewControllerTests : XCTestCase
@end

@implementation ViewControllerTests

- (void)testExample
{ 
    // Using a class that is not in the test target.
    ViewController * viewController = [[ViewController alloc] init];
    XCTAssertNotNil(viewController, @"");
}

@end

ViewController.h 是not测试目标的一部分,但这可以毫无问题地编译和运行测试。

我认为这是因为应用程序是首先构建的(作为依赖项),然后是测试。然后链接器会找出 ViewController 类是什么。

但是,在较旧的项目中,使用完全相同的测试和 ViewController 文件,构建在链接器阶段失败:

Undefined symbols for architecture i386:
"_OBJC_CLASS_$_ViewController", referenced from:
  objc-class-ref in ViewControllerTests.o

即使创建新的 XCTest 单元测试目标,也会发生此链接器错误。

为了解决这个问题,可以将源代码包含在应用程序和测试目标中(勾选上图中的两个框)。这会导致模拟器的系统日志中出现重复符号的构建警告(打开模拟器并按 cmd-/ 查看此内容):

Class ViewController is implemented in both 
[...]/iPhone Simulator/ [...] /MyApp.app/MyApp and 
[...]/Debug-iphonesimulator/LogicTests.octest/LogicTests. 
One of the two will be used. Which one is undefined.

这些警告有时会导致以下示例所示的问题:

 [viewController isKindOfClass:[ViewController class]]; // = NO
 // Memory address of the `Class` objects are different.

 NSString * instanceClassString = NSStringFromClass([viewController class]);
 NSString * classString         = NSStringFromClass([ViewController class]);

 [instanceClassString isEqualToString:classString]; // = YES
 // The actual class names are identical

所以问题是旧项目中的哪些设置要求应用程序源文件包含在测试目标中?


意见摘要

工作项目和非工作项目之间:

  1. 链接器输出没有区别(以Ld).
  2. 目标依赖项没有区别(测试目标有 1 个依赖项,即应用程序)
  3. 链接器设置没有区别。

我花了一些时间来解决这个问题。

如果你读过本文档 https://developer.apple.com/legacy/library/documentation/DeveloperTools/Conceptual/UnitTesting/02-Setting_Up_Unit_Tests_in_a_Project/setting_up.html您会发现 Xcode 有两种运行测试的模式。逻辑测试和应用测试。不同之处在于逻辑测试使用内置的类和符号构建自己的目标。生成的可执行文件可以在模拟器中运行,并将测试输出报告回 Xcode。另一方面,应用程序测试构建一个链接到您的代码的动态库,该代码在运行时注入到应用程序中。这允许您在 iPhone 环境中运行测试并测试 Xib 加载和其他事情。

由于取消链接源文件时测试目标中缺少符号,因此您的旧项目似乎配置了用于逻辑测试的测试目标,而不是应用程序(单元)测试。

如今 Xcode 似乎是试图不区分两者 http://openradar.appspot.com/15859153并默认创建应用程序测试目标,让我们逐步了解您可能需要更改的所有内容,以将逻辑测试目标转变为单元测试目标。

我还将假设您有一个应用程序目标而不是静态库目标,因为方向会略有不同。

  1. 在测试目标的构建设置中删除“Bundle Loader”和“Test Host”构建设置。我们稍后会让 Xcode 将它们添加回来
  2. 您需要从测试目标中删除应用程序中的所有 .m 文件。您可以通过选择所有 .m 文件并在 Xcode 文件检查器中删除测试目标来完成此操作,也可以使用测试目标的编译源构建阶段。
  3. 更改测试目标的“框架搜索路径”。对于 Xcode 5,它们应该是$(SDKROOT)/Developer/Library/Frameworks $(inherited) $(DEVELOPER_FRAMEWORKS_DIR) 按此顺序和没有额外的引号或反斜杠 https://stackoverflow.com/questions/18652963/xctest-framework-build-error
  4. 转到测试目标构建设置的“常规”窗格,然后从下拉菜单中选择您的目标。如果菜单已指定您的应用程序目标,您应该将其关闭然后再次打开。这将使 Xcode 使用正确的值重新配置捆绑加载程序和测试主机设置。
  5. 最后仔细检查您的应用程序的方案。在方案下拉列表中选择编辑方案。然后单击测试操作。确保您的测试目标位于信息窗格的列表中,并确保选择了所有测试。

此信息或多或少来自上面链接的文档,但我更新了 Xcode 5 的步骤。

EDIT:

嗯 100% 请注意 eph515 关于调试符号可见的说法,但您可能还想检查是否有人没有将您的方案的测试操作设置为在Release或其他配置。单击方案选择器并选择编辑方案。单击测试操作,然后确保构建配置是Debug

如果您有静态库目标

因此,如果您有静态库目标,您有两个选择: 1. 逻辑测试 2. 主机应用程序中的应用程序测试

对于1.你必须确保Bundle Loader and Test Host对于您的静态库目标来说是空的。然后,您的源代码必须编译到测试目标中,因为它们没有其他方式可以运行。

对于2.您需要在Xcode中创建一个新的应用程序项目并将您的静态库项目添加为子项目。然后您需要手动复制Bundle Loader and Test Host将设置从新应用程序的测试目标构建到静态库测试目标。然后,打开新测试应用程序的方案,并将测试目标添加到新应用程序的测试操作中。 要在您的库上运行测试,您需要为您的主机应用程序运行测试操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

何时需要将应用程序源包含在测试目标中? 的相关文章

随机推荐

  • 设置默认的 apache 虚拟主机

    除了选择它找到的第一个配置之外 还有其他更好的方法来设置默认的 apache 虚拟主机吗 我有一台包含许多域的服务器 其中只有一些域配置了 httpd 但默认的虚拟主机被切断 例如 aaa com 我真的希望它默认为 mmm com 吗 像
  • 已知起点和距离计算第二点

    使用纬度和经度值 A 点 我尝试计算另一个点 B 距离 A 点 X 米 距离 A 点 0 弧度 然后显示 B 点的纬度和经度值 示例 伪代码 PointA Lat x xxxx PointA Lng x xxxx Distance 3 Me
  • 如何在 Python 中打印 Unicode 字符代码?

    我想打印 unicode 的字符代码 而不是它在 Python 中表示的实际字形 例如 如果u是 unicode 字符列表 gt gt gt u 0 u u0103 gt gt gt print u 0 我想将字符代码输出为原始字符串 u
  • 设置 Github Commit RSS 源

    我正在尝试将我的 github 提交为 RSS feed 但到目前为止我还没有弄清楚 我知道私人提要可使用以下语法 https github com username atom token token 但这是用户的活动源 我想要我的一个项目
  • 如何使用 DynamoDB 进行基本聚合?

    dynamodb 是如何实现聚合的 Mongodb 和 couchbase 具有地图缩减支持 假设我们正在建立一个技术博客 用户可以在其中发布文章 并说文章可以被标记 user id 1235 name John article id 78
  • 在 R 中加载具有最新日期的文件[重复]

    这个问题在这里已经有答案了 假设我有一个文件想要在 R 中加载 让我们称之为file csv 将其加载到 R 中相当容易 不幸的是 在我的情况下 存在该文件的多个版本 并且每个文件都附加了一个日期 所以我的目录中真正拥有的是文件列表 例如
  • Gem::Ext::BuildError: 错误: 无法在 macOS Monterey 上构建 gem 本机扩展

    当我跑步时bundle install在我的 Rails 5 项目中 我在似乎具有本机扩展的 gem 上遇到了许多错误 以下是其中一个 gem 的输出顶部 Installing nio4r 1 2 1 with native extensi
  • Python 测试:使用带有 mock 和 io.StringIO 的假文件

    我正在尝试测试一些在文件上运行的代码 但我似乎无法理解如何使用真实文件替换mock and io StringIO我的代码大致如下 class CheckConfig object def init self config self con
  • Visual Basic UDPClient 服务器/客户端模型?

    因此 我正在尝试制作一个非常简单的系统 将消息从客户端发送到服务器 后来也从服务器发送到客户端 但首先是婴儿步骤 我不确定如何使用 UDPClient 发送和接收消息 尤其是接收消息 主要是因为我没有任何东西触发ReceiveMessage
  • 什么样的 Lua 多线程包在发布时“正常工作”?

    在 Lua 中编码时 我有一个三重嵌套循环 经过 6000 次迭代 所有 6000 次迭代都是独立的 并且可以轻松并行化 Lua 封装了哪些线程开箱即用编译 and 获得不错的并行加速在四个或更多核心上 到目前为止我所知道的是 luapro
  • iTunes Connect 应用程序分析、销售和趋势显示不同的值

    因此 当我访问 iTunes Connect 然后访问 销售和趋势 时 它显示我有 5 万台 我单击 设备 它显示 45k 来自桌面设备 4k 来自 iPhone 1k 来自 iPad 对我来说这看起来真的很奇怪 然后我进入 App Ana
  • FullCalendar - 向事件对象添加新属性

    有很多线程讨论类似的问题 但没有一个我能真正理解并应用于我的项目 我有一个数据库 其中包含一个包含多个字段的事件表 字段 1 字段 2 字段 3 我有一个 PHP 文件 json php 该文件 json encode 将该表转换为 JSO
  • ContentControl + RenderTargetBitmap + 空图像

    我试图创建一些图表图像 而不在屏幕上显示这些图表 我已经做了很长一段时间并尝试了很多不同的事情 但似乎没有任何效果 如果我首先在窗口中显示图表 则代码可以完美运行 但是如果我不在窗口中显示它 则位图只是带有黑色边框的白色 不知道为什么 我尝
  • 访问原始 Apache Web 服务器请求

    我打算设计一个网络 GPS 跟踪应用程序 GPS 使用 TCP 无 HTTP 标头 在端口 7070 我打算将其更改为 80 上传输数据 我知道 GPS 跟踪器和客户端之间的通信协议 但是我被困住了 因为我无法拦截网络服务器上的数据包 由于
  • 无法运行项目 - Android Studio 2.0 Crashlytics 问题

    我将 Android Studio 更新到 2 0 并尝试让即时运行正常工作 Gradle 同步有效 重建项目正在进行中 尝试运行 失败 我究竟做错了什么 变量 io fabric tools gradle 1 14 4 com andro
  • :hover 在拖放时粘在元素上

    我有简单的 ol li 结构 想添加拖放功能 此外 我想以不同的颜色突出显示悬停项目和拖动项目 但这是 WebKit 中的一个不寻常的错误 捕获最后一个项目 将其拖到顶部 将其拖放到第一项 最后一个元素捕获悬停伪类 为什么 我该如何预防 这
  • 代码语法荧光笔[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找自动语法荧光笔 当我指定代码的起点和终点时 语法突出显示应自动识别代码类型 例如 sql v
  • Android SSLEngine 示例

    我需要为我正在开发的应用程序使用基于 TLS 的 TCP 套接字 我已经经历了几十个例子 虽然我没有问题地完成握手 但我似乎无法通过任何方式读取输入流 尝试了很多 包括 readline 读取字符数组等 每次我尝试时 应用程序都会在该位置冻
  • Netbeans 中的 hibernate 逆向工程找不到 SQL Server 表

    我的机器上安装了测试 SQL Server 数据库 创建了一个测试 SQL Server 帐户 并使用该帐户在 TestDb 中的默认架构上创建了两个表 在我的 Java Web 应用程序 简单的 JSP 上 我使用 Hibernate 并
  • 何时需要将应用程序源包含在测试目标中?

    在一个新项目中我有这个简单的测试 import