Objective-C 是不是有任何基于非 Xcode 的命令行单元测试工具?

Posted

技术标签:

【中文标题】Objective-C 是不是有任何基于非 Xcode 的命令行单元测试工具?【英文标题】:Is there any non-Xcode-based command line unit testing tool for Objective-C?Objective-C 是否有任何基于非 Xcode 的命令行单元测试工具? 【发布时间】:2013-03-30 02:43:52 【问题描述】:

Compiling Objective-C without GUI 的帖子内容如下:

要在 OSX 上编译 Objective-C,您必须获得 XCode,它可以从 Application Store 免费获得。获取 XCode 将确保您获得必要的框架(头文件),例如 Foundation、Cocoa 等。但是,这不会为您提供从命令行编译 Object-C 所需的命令行工具。打开 XCode,转到首选项 > 下载 > 组件并安装命令行工具。这将安装 gcc、clang、make 等。

我正在寻找一个非基于 Xcode 的工具来解决我的问题,我刚刚打开:Is it possible to make an Objective-C project to be tested on Travis?

此工具应满足以下要求:

它应该与 Xcode 没有任何关系。 下面的简单程度就足够了:只是一些 int main 代码收集附近的所有测试用例文件并在我要测试的代码上运行测试断言(如 SetTestingKit 中的 ST- 或 GHUnit 中的 GH-) 我不需要 UI、GUI、Xcode、模拟器。 如果它可以在 Mac 和 Ubuntu(是的,Travis)上运行,那会很棒,可能使用 GNUstep 就像引用的帖子所描述的那样。

根据接受的答案更新:

根据 Malte Tancred 在接受的答案中所说的,以下简单设置似乎足以满足我当前的需求:

三个文件,都在我项目的tests目录下:

octest.m

#import <Foundation/Foundation.h>
#import <SenTestingKit/SenTestingKit.h>

int main() 
    @autoreleasepool 
        SenSelfTestMain();
    

    return 0;

生成文件

CC=clang # or gcc

# Trick to get current dir: https://***.com/questions/322936/common-gnu-makefile-directory-path
TESTS_DIR:= $(dir $(lastword $(MAKEFILE_LIST)))
PROJECT_DIR:= $(TESTS_DIR)/..

FRAMEWORKS_PATH:= -F/Applications/Xcode.app/Contents/Developer/Library/Frameworks
FRAMEWORKS:= -framework Foundation -framework SenTestingKit
LIBRARIES:= -lobjc
INCLUDE_PATHS:= -I$(PROJECT_DIR)/Projectfiles\
                -I$(TESTS_DIR)/TestHelpers

SOURCE_FILES = $(wildcard $(PROJECT_DIR)/Projectfiles/*.m)

SOURCE_TEST_SUITE = $(wildcard $(TESTS_DIR)/Tests/*.m)

SOURCE_TESTS = $(TESTS_DIR)/TestHelpers/TestHelpers.m\
                 octest.m


CFLAGS=-Wall -Werror -fobjc-arc -g -v $(SOURCE_FILES) $(SOURCE_TEST_SUITE) $(SOURCE_TESTS)
LDFLAGS=$(LIBRARIES) $(FRAMEWORKS)
OUT=-o octest

all:
    $(CC) $(FRAMEWORKS_PATH) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(OUT)

运行测试

#!/bin/bash
export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks
make
./octest

更新捕获退出代码:

在我提出这个问题几天后,Travis 宣布支持 Objective-C:

http://about.travis-ci.org/blog/introducing-mac-ios-rubymotion-testing/

虽然他们建议使用默认脚本进行构建,但我决定采用此处描述的方法,仍然使用 octest 而不是 Travis 使用的 xcodebuild 方法。

默认情况下,travis 设置依赖于 Justin Spahr-Summers 编写的构建脚本:https://github.com/jspahrsummers/objc-build-scripts:

他们使用 awk 从 xcodebuild 的输出中捕获退出代码,因为它总是以 0 退出代码存在,即使整个测试套件都失败了!

OCTest 的行为方式相同 - 它始终以 0 代码存在,这就是我使用 Travis awk 脚本的简化版本以满足我在上面描述的方式构建它的需要的方式:

octest.awk

# Exit statuses:
#
# 0 - No errors found.
# 1 - Build or test failure. Errors will be logged automatically.

BEGIN 
    status = 0;



    print;
    fflush(stdout);


/[0-9]+: (error|warning):/ 
    errors = errors $0 "\n";


/with [1-9]+ failures?/ 
    status = 1;


END 
    if (length(errors) > 0) 
        print "\n*** All errors:\n" errors;
    

    fflush(stdout);
    exit status;

运行测试

#!/bin/bash

export DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks

make

runtests ()

  ./octest 2>&1 | awk -f "octest.awk"

  local awkstatus=$?

  if [ "$awkstatus" -eq "1" ]
  then
    echo "Test suite failed"
    return $awkstatus
  else
    echo "Test suite passed"
    return 0
  fi


echo "*** Building..."

runtests || exit $?

【问题讨论】:

【参考方案1】:

有非 Mac 平台的 objcunit 端口。您可以查看 MidnightBSD 中的 port 与 GNUstep 一起使用。这些补丁也应该适用于其他环境。 pkg-descr 有软件包网站,Makefile 有下载 URL。

【讨论】:

另见 Github:github.com/tancred/ObjcUnitPrototype:“我正在试验新版本的 ObjcUnit,这是我在 2001/2002 年与我的朋友和同事 Peter Lindberg。ObjcUnit 是 jUnit 对 Objective-C 的改编(几乎是直接翻译)..."【参考方案2】:

您的主要问题的答案是肯定的: Objective-C 有命令行测试工具 不依赖于 Xcode。

例如, 您可以在不使用 Xcode 的情况下使用 OCUnit/SenTestingKit。 所有你需要做的 是将您的编译器/链接器指向框架。 考虑以下文件,octest.m

#import <Foundation/Foundation.h>
#import <SenTestingKit/SenTestingKit.h>

int main() 
  @autoreleasepool 
    SenSelfTestMain();
  
  return 0;


@interface MyTest : SenTestCase
@end

@implementation MyTest
- (void)testSomething 
  STAssertEquals(1, 2, @"fail");

@end

编译:

clang -o octest octest.m -F/Applications/Xcode.app/Contents/Developer/Library/Frameworks -framework Foundation -framework SenTestingKit

现在运行它

DYLD_FRAMEWORK_PATH=/Applications/Xcode.app/Contents/Developer/Library/Frameworks ./octest

你应该看到类似的东西

Test Suite '/tmp/octest(Tests)' started at 2013-04-04 12:34:49 +0000
Test Suite 'MyTest' started at 2013-04-04 12:34:49 +0000
Test Case '-[MyTest testSomething]' started.
octest.m:16: error: -[MyTest testSomething] : '1' should be equal to '2': fail
Test Case '-[MyTest testSomething]' failed (0.000 seconds).
Test Suite 'MyTest' finished at 2013-04-04 12:34:49 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds
Test Suite '/tmp/octest(Tests)' finished at 2013-04-04 12:34:49 +0000.
Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.001) seconds
make: *** [default] Error 1

这个例子确实依赖于 Xcode 因为它使用捆绑的 SenTestingKit 框架 但是构建和运行测试的一般过程 如上所述 不依赖于 Xcode。

现在, 让它在 linux 系统上运行 你必须安装 SenTestingKit(很可能是 GNUstep), 但是有了这些组件 构建和测试过程应该基本相同。

【讨论】:

非常感谢您的回答。我不知道'SenSelfTestMain()'。您能否扩展您的答案并告诉我如何使用您的示例“收集附近的所有测试用例 .m 文件,就像 Xcode 在测试目标中所做的那样”(例如:如果 MyTest 在单独的 MyTest.m 中怎么办?文件,不在同一个 octest.m 文件中?)。抱歉,如果我问的是非常简单的问题 - 我是以“从上到下”的方式学习 C/Objective-C 的人,从 Xcode 级别到地面。 啊,最简单的办法就是在main()函数上面加上#import "MyTest.m",对吗?我就是这样工作的。 在使用自动测试发现时,您不必#import 任何头文件。只需确保将测试用例链接到可执行文件中,或者在运行时动态加载它们,SenSelfTestMain() 就会找到测试。这就是 Xcode 中发生的事情;它运行otest 可执行文件,然后加载包含测试用例的测试包。 多么有用的知识!在我阅读您的评论之前 10 或 15 分钟,我自己发现了它。再次感谢。【参考方案3】:

对于编译objective-C,我知道一种快速而肮脏(而且有些有限)的方法——我在http://www.compileonline.com/compile_objective-c_online.php 在线进行。也就是说,这个编译器会抛出很多 c-99 错误,我认为这是因为它是 C 的严格超集,并且不包括该语言的一些更独特的特性(例如:@synthesize,甚至点符号) ,但它完成了工作。我用 Notepad++ 输入代码。就像我说的那样,有限,但外科手术。 *此外 - 它支持命令行样式输入,这是可靠的。

【讨论】:

感谢您的回答。在我看来,您解决的问题与我在这里提出的问题不同:我的目标是找到单元测试工具!而不是手动测试 Objective-C 代码的可能性!无论如何感谢您的链接,不知道。【参考方案4】:

查看来自 facebook 的 xctool,它是 Apple 的 xcodebuild 的替代品。我们使用 maven 构建了我们的 Objective-C 库,并且仅将其用于测试而不是 xcodebuild,并且效果很好。与xcodebuild 相比,输出更具可读性。

来自xctool 页面,

xctool is a replacement for Apple's xcodebuild that makes it easier to build 
and test iOS and Mac products. 

需要注意的一点是它不支持构建目标。不过,您可以使用方案。

【讨论】:

以上是关于Objective-C 是不是有任何基于非 Xcode 的命令行单元测试工具?的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于块的 API 方法中使用非空和可为空的 Objective-C 关键字

Python 是不是有任何异步非网络 I/O 框架?

ID3 标记 Objective-C

你如何同时为*所有*手机/移动设备写作?

从非视图类获取presentViewController(Objective-C)

选取适合应用程序的数据和视图部分的方法