Xcode 使用xctest 和RunTargetUnitTests 脚本(来自/Developer/Tools/RunTargetUnitTests)进行单元测试。
xctest 将dynamic library(具有单独线程用于其作业的测试工具包)注入您的二进制文件,注入使dylib 访问您的进程内存(它可以访问您进程内存中的类/实例),它能够执行调用和进行单元测试。来自设备/模拟器的回调是从调试器接收的(没有特殊的单元测试技术)。
简单地说:test scheme的项目照常编译,但它链接的动态库会木马你的进程内存,并进行测试。
还有非常有用的信息:
RunUnitTests 接受ENVIRONMENT variables,这里有一些有趣的
TEST_HOST - 要“注入”的可执行文件的完整路径
指定的单元测试包。对于应用程序,这必须是完整的
应用程序在其包装器中的路径。不要为框架设置这个
作品或图书馆。
TEST_RIG - 可执行文件的完整路径以用作测试装备
CPlusTestRig 或 otest。可执行文件必须采用路径
到一个测试包作为它的最后一个参数。它的 DYLD_FRAMEWORK_PATH 和
DYLD_LIBRARY_PATH 将被配置为指向 BUILT_PRODUCTS_DIR
在执行之前。如果您使用的是默认值之一,请不要设置此项
试验台。
还
BUNDLE_LOADER 用作链接器选项,表示链接器将Testing dynamic library 链接到您指定的二进制文件中。
测试包目标模板的最后有一个 shell 脚本构建阶段,它调用 /Developer/Tools/RunUnitTests。 RunUnitTests 查看通过其环境传递的构建设置,并根据该信息确定如何在测试包中运行测试。
如果您正在测试一个框架,RunUnitTests 将运行适当的测试装备并告诉它加载和运行您的包中的测试。由于您的测试包应该链接到您的框架,因此您的框架将在测试平台加载您的包时加载。
如果您正在测试应用程序,则需要在其配置的构建设置中将该应用程序指定为测试包的测试主机和包加载器。 Bundle Loader 设置告诉链接器将您的包链接到正在加载它的应用程序,就好像应用程序是一个框架一样,允许您从包中引用应用程序中的类和其他符号,而无需实际将它们包含在包中。测试主机设置告诉 RunUnitTests 启动指定的应用程序并将您的测试包注入其中以运行其测试。
有关更多信息,请参阅man 页的RunTargetUnitTests/xctest
https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/RunTargetUnitTests.1.html#//apple_ref/doc/man/1/RunTargetUnitTests
https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man1/xctest.1.html
这是RunTargetUnitTests 脚本
#!/bin/sh
#
# 版权所有 (c) 2005-2013 Apple Inc. 保留所有权利。
#
# 版权所有 (c) 1997-2005,Sen:te (Sente SA)。版权所有。
#
# 此源代码的使用受以下许可的约束:
#
# 以源代码和二进制形式重新分发和使用,无论是否修改,
# 是允许的,前提是满足以下条件:
#
# (1) 再分发源代码必须保留以上版权声明,
# 此条件列表和以下免责声明。
#
# (2) 以二进制形式再分发必须复制上述版权声明,
# 此条件列表和文档中的以下免责声明
# 和/或随分发提供的其他材料。
#
# 本软件由版权所有者和贡献者“按原样”提供
# 以及任何明示或暗示的保证,包括但不限于暗示的保证
# 对适销性和特定用途适用性的保证不予承认。
# 在任何情况下,Sente SA 或贡献者均不对任何直接、间接、附带、
# 特殊、惩戒性或后果性损害(包括但不限于采购
# 替代商品或服务;使用、数据或利润的损失;或业务中断)
# 无论是出于何种原因和基于任何责任理论,无论是合同责任还是严格责任,
# 或以任何方式因使用本软件而产生的侵权行为(包括疏忽或其他),
# 即使被告知此类损害的可能性。
#
# 注意:此许可证等同于 FreeBSD 许可证。
#
# 此通知可能不会从该文件中删除。
如果 [ "${NATIVE_ARCH_ACTUAL}" = "" ];然后
NATIVE_ARCH_ACTUAL=`拱`
菲
如果 [ "${ARCHS}" = "" ];然后
ARCHS=`拱`
菲
如果 [ "${DEVELOPER_DIR}" = "" ];然后
DEVELOPER_DIR="${SYSTEM_DEVELOPER_DIR}"
菲
如果 [ "${OTEST}" = "" ];然后
OTEST="${DEVELOPER_DIR}/Tools/otest"
菲
如果 [ "${OTEST_TARGET}" = "" ];然后
OTEST_TARGET="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}"
菲
RunTargetUnitTestsForArch() {
echo "${DEVELOPER_DIR}/Tools/RunTargetUnitTests:0: 注意:开始测试 ${1}"
如果 [ "${DYLD_FRAMEWORK_PATH}" = "" ] ;然后
DYLD_FRAMEWORK_PATH="${BUILT_PRODUCTS_DIR}:${DEVELOPER_DIR}/Library/Frameworks"
别的
DYLD_FRAMEWORK_PATH="${BUILT_PRODUCTS_DIR}:${DEVELOPER_DIR}/Library/Frameworks:${DYLD_FRAMEWORK_PATH}"
菲
导出 DYLD_FRAMEWORK_PATH
回声“OTEST=${OTEST}”
拱 -arch "${1}" "${OTEST}" "${OTEST_TARGET}"
取消设置 DYLD_FRAMEWORK_PATH
echo "${DEVELOPER_DIR}/Tools/RunTargetUnitTests:0: 注意:${1} 的已完成测试"
}
SkipTargetUnitTestsForArch() {
echo "${DEVELOPER_DIR}/Tools/RunTargetUnitTests:0: 注意:跳过 ${1} 的测试"
}
如果 [ "${TEST_AFTER_BUILD}" = "YES" ];然后
# 每个请求和支持的架构运行一次单元测试。
${ARCHS} 中的 TEST_ARCH;做
案例“${NATIVE_ARCH_ACTUAL}”在
i386)
如果 [ "${TEST_ARCH}" = "i386" ];然后
RunTargetUnitTestsForArch "${TEST_ARCH}"
别的
SkipTargetUnitTestsForArch "${TEST_ARCH}"
菲
;;
x86_64)
如果 [ "${TEST_ARCH}" = "i386" -o "${TEST_ARCH}" = "x86_64" ];然后
RunTargetUnitTestsForArch "${TEST_ARCH}"
别的
SkipTargetUnitTestsForArch "${TEST_ARCH}"
菲
;;
*)
RunTargetUnitTestsForArch "${TEST_ARCH}"
;;
经社理事会
完毕
菲