xcknife 0.6.3 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a16ad712fe21666c9ec13b16c1cc3007120bc9eb
4
- data.tar.gz: fc3109c894275ca6c8e5fed344fd35a3a11d0457
2
+ SHA256:
3
+ metadata.gz: d5e951e4ae5d93f82ed7773becf567d9ce8dc3a10295b3c9b7774617e1a10d48
4
+ data.tar.gz: 5f9cfc34b089ec42bf675280fd3fbf0da524220c79a55e0297ada05d0e3403d6
5
5
  SHA512:
6
- metadata.gz: f364876c260015cc6b0729035c5835b295e1772b27671b50448064659841ab21e2384476b4e5860387e0f397db41d80f4fe48730b6e36879776295e18d89056d
7
- data.tar.gz: 456da664e95295f2ae4a20982b245e7ade3a616047cf89dd654e0de0d5d053f2d1a11da6b9bc88b8f1099fd917111f7ed963a112b9c3c2cde6c50056a406a00d
6
+ metadata.gz: a57b87ee14efa242124ad9e14c2d7bc86937315a8dc9e9206c80480285c4744495ad4376f02ad835f7c23e52e79ebbbc7f7cbcab9ba95a3b12d894aaed0daca9
7
+ data.tar.gz: 07afb2bc56b4792c355a89001cce7d45261358375457cff69f717b73ce3dbfb0c69ac91fee0b01714d1a8761869bbf1475c0044064aa74ae8e20023ef0fc8481
data/.gitignore CHANGED
@@ -2,9 +2,10 @@
2
2
  pkg
3
3
  .idea/
4
4
  *.gem
5
- Gemfile.lock
6
5
  xcuserdata/
7
6
  testdumperbuild
8
7
  contents.xcworkspacedata
9
8
  TestDumper/TestDumper.dylib
10
9
  *.tmp
10
+ .bin/
11
+ .bundle/
@@ -1 +1 @@
1
- 2.2.3
1
+ 2.6.1
@@ -1,9 +1,14 @@
1
- language: ruby
1
+ language: objective-c
2
2
  sudo: false
3
- before_install: gem install bundler
4
- bundler_args: --without development
3
+ matrix:
4
+ include:
5
+ - os: osx
6
+ osx_image: xcode10.2
5
7
 
6
- rvm:
7
- - 2.2.3
8
- - 2.3.0
9
- - 2.3.1
8
+ before_script:
9
+ - export LANG=en_US.UTF-8
10
+ install: bundle
11
+ script:
12
+ - csrutil status
13
+ - git submodule update --init --recursive
14
+ - bundle exec rake build_test_dumper spec
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ xcknife (0.11.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.3)
10
+ rake (11.1.2)
11
+ rspec (3.4.0)
12
+ rspec-core (~> 3.4.0)
13
+ rspec-expectations (~> 3.4.0)
14
+ rspec-mocks (~> 3.4.0)
15
+ rspec-core (3.4.4)
16
+ rspec-support (~> 3.4.0)
17
+ rspec-expectations (3.4.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.4.0)
20
+ rspec-mocks (3.4.1)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.4.0)
23
+ rspec-support (3.4.1)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ bundler (~> 1.12)
30
+ rake (~> 11.1.1)
31
+ rspec (~> 3.4.0)
32
+ xcknife!
33
+
34
+ BUNDLED WITH
35
+ 1.17.3
@@ -0,0 +1,2 @@
1
+ ---
2
+ cc: [mdx-ios]
data/README.md CHANGED
@@ -9,7 +9,7 @@ It works by leveraging [xctool's](https://github.com/facebook/xctool) [json-stre
9
9
 
10
10
  XCKnife generates a list of only arguments meant to be pass to Xctool's [*-only* test arguments](https://github.com/facebook/xctool#testing), but alternatively could used to generate multiple xcschemes with the proper test partitions.
11
11
 
12
- More information on XCKnife, go [here](https://corner.squareup.com/2016/06/xcknife-faster-distributed-tests-for-ios.html).
12
+ More information on XCKnife, go [here](https://developer.squareup.com/blog/xcknife-faster-distributed-tests-for-ios).
13
13
 
14
14
  ## Install
15
15
 
@@ -18,11 +18,12 @@ More information on XCKnife, go [here](https://corner.squareup.com/2016/06/xckni
18
18
  ## Using as command line tool
19
19
 
20
20
  ```
21
- $ xcknife -h
21
+ $ xcknife --help
22
22
  Usage: xcknife [options] worker-count historical-timings-json-stream-file [current-tests-json-stream-file]
23
- -p, --partition TARGETS Comma separated list of targets. Can be used multiple times
23
+ -p, --partition TARGETS Comma separated list of targets. Can be used multiple times.
24
24
  -o, --output FILENAME Output file. Defaults to STDOUT
25
25
  -a, --abbrev Results are abbreviated
26
+ -x, --xcodebuild-output Output is formatted for xcodebuild
26
27
  -h, --help Show this message
27
28
  ```
28
29
 
@@ -68,7 +69,7 @@ This will balance the tests onthe `iPhoneTestTarget` into 3 machines. The output
68
69
  }]}]}
69
70
  ```
70
71
 
71
- This provides a lot of data about the partitions and their imabalances (both internal to the partition sets, and amongst them).
72
+ This provides a lot of data about the partitions and their imbalances (both internal to the partition sets, and amongst them).
72
73
 
73
74
  If you only want the *-only* arguments, run with the `-a` flag:
74
75
 
@@ -193,6 +194,14 @@ XCKnife uses only a few attributes of a json-stream file. If you are storing the
193
194
 
194
195
  `$ xcknife-min example/xcknife-exemplar-historical-data.json-stream minified.json-stream`
195
196
 
197
+ ## Dependencies
198
+
199
+ XCKnife requires the use of the `gtimeout` command, which is provided in the GNU coreutils brew package. If you don't already have them, they can be installed with the command:
200
+
201
+ ```
202
+ brew install coreutils
203
+ ```
204
+
196
205
  ## Contributing
197
206
 
198
207
  Any contributors to the master *xcknife* repository must sign the
data/Rakefile CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'rspec/core/rake_task'
2
- require "bundler/gem_tasks"
3
2
  require 'fileutils'
4
3
 
5
4
  RSpec::Core::RakeTask.new(:spec)
@@ -11,7 +10,7 @@ task :build_test_dumper do
11
10
  target_dir = File.join(File.dirname(__FILE__), "TestDumper")
12
11
  Dir.chdir(target_dir) do
13
12
  system "./build.sh"
14
- FileUtils.copy_file("./testdumperbuild/Build/Products/Release-iphonesimulator/TestDumper.framework/TestDumper", "./TestDumper.dylib")
13
+ FileUtils.copy_file("./testdumperbuild/Build/Products/Debug-iphonesimulator/TestDumper.framework/TestDumper", "./TestDumper.dylib")
15
14
  puts "TestDumper.dylib was created successfully"
16
15
  end
17
16
  end
@@ -19,4 +18,5 @@ end
19
18
  desc "Release wih test_dumper"
20
19
  task :gem_release => [:build_test_dumper, :build] do
21
20
  system 'gem push pkg/xcknife-*.gem'
22
- end
21
+ end
22
+
@@ -1,6 +1,6 @@
1
1
  # TestDumper - EXPERIMENTAL
2
2
 
3
- Utility that replaces xctool for enumerating tests. It requires the `build-for-testing` feature Xcode8 introduced on xcodebuild. In particular, it leverages the xctestrun file (see `man xcodebuild.xctestrun`).
3
+ Utility that replaces xctool for enumerating tests. It requires the `build-for-testing` feature Xcode 8 introduced on xcodebuild. In particular, it leverages the xctestrun file (see `man xcodebuild.xctestrun`).
4
4
 
5
5
  ## Building.
6
6
 
@@ -8,4 +8,18 @@ Run
8
8
 
9
9
  ```
10
10
  $ ./build.sh
11
- ````
11
+ ````
12
+
13
+ ## Using as command line tool
14
+
15
+ ```
16
+ $ xcknife-test-dumper --help
17
+ Usage: xcknife-test-dumper [options] derived_data_folder output_file [device_id]
18
+ -d, --debug Debug mode enabled
19
+ -r, --retry-count COUNT Max retry count for simulator output
20
+ -x, --simctl-timeout SECONDS Max allowed time in seconds for simctl commands
21
+ -t OUTPUT_FOLDER, Sets temporary Output folder
22
+ --temporary-output
23
+ -s, --scheme XCSCHEME_FILE Reads environments variables from the xcscheme file
24
+ -h, --help Show this message
25
+ ```
@@ -181,7 +181,7 @@
181
181
  isa = PBXProject;
182
182
  attributes = {
183
183
  LastSwiftUpdateCheck = 0700;
184
- LastUpgradeCheck = 0700;
184
+ LastUpgradeCheck = 1010;
185
185
  ORGANIZATIONNAME = "Square, Inc";
186
186
  TargetAttributes = {
187
187
  F60C68B91B8D038300CC8521 = {
@@ -198,7 +198,7 @@
198
198
  };
199
199
  };
200
200
  };
201
- buildConfigurationList = F60C68B41B8D038300CC8521 /* Build configuration list for PBXProject "toolc" */;
201
+ buildConfigurationList = F60C68B41B8D038300CC8521 /* Build configuration list for PBXProject "TestDumper" */;
202
202
  compatibilityVersion = "Xcode 3.2";
203
203
  developmentRegion = English;
204
204
  hasScannedForEncodings = 0;
@@ -288,13 +288,23 @@
288
288
  CLANG_CXX_LIBRARY = "libc++";
289
289
  CLANG_ENABLE_MODULES = YES;
290
290
  CLANG_ENABLE_OBJC_ARC = YES;
291
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
291
292
  CLANG_WARN_BOOL_CONVERSION = YES;
293
+ CLANG_WARN_COMMA = YES;
292
294
  CLANG_WARN_CONSTANT_CONVERSION = YES;
295
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
293
296
  CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
294
297
  CLANG_WARN_EMPTY_BODY = YES;
295
298
  CLANG_WARN_ENUM_CONVERSION = YES;
299
+ CLANG_WARN_INFINITE_RECURSION = YES;
296
300
  CLANG_WARN_INT_CONVERSION = YES;
301
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
302
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
303
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
297
304
  CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
305
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
306
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
307
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
298
308
  CLANG_WARN_UNREACHABLE_CODE = YES;
299
309
  CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
300
310
  "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -337,13 +347,23 @@
337
347
  CLANG_CXX_LIBRARY = "libc++";
338
348
  CLANG_ENABLE_MODULES = YES;
339
349
  CLANG_ENABLE_OBJC_ARC = YES;
350
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
340
351
  CLANG_WARN_BOOL_CONVERSION = YES;
352
+ CLANG_WARN_COMMA = YES;
341
353
  CLANG_WARN_CONSTANT_CONVERSION = YES;
354
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
342
355
  CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
343
356
  CLANG_WARN_EMPTY_BODY = YES;
344
357
  CLANG_WARN_ENUM_CONVERSION = YES;
358
+ CLANG_WARN_INFINITE_RECURSION = YES;
345
359
  CLANG_WARN_INT_CONVERSION = YES;
360
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
361
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
362
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
346
363
  CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
364
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
365
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
366
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
347
367
  CLANG_WARN_UNREACHABLE_CODE = YES;
348
368
  CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
349
369
  "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -373,12 +393,13 @@
373
393
  F60C68D11B8D038300CC8521 /* Debug */ = {
374
394
  isa = XCBuildConfiguration;
375
395
  buildSettings = {
396
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
376
397
  CLANG_ENABLE_MODULES = YES;
398
+ CODE_SIGN_IDENTITY = "";
377
399
  DEFINES_MODULE = YES;
378
400
  DYLIB_COMPATIBILITY_VERSION = 1;
379
401
  DYLIB_CURRENT_VERSION = 1;
380
402
  DYLIB_INSTALL_NAME_BASE = "@rpath";
381
- EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
382
403
  FRAMEWORK_SEARCH_PATHS = (
383
404
  "$(inherited)",
384
405
  "$(SDKROOT)/../../Library/Frameworks/",
@@ -399,12 +420,13 @@
399
420
  F60C68D21B8D038300CC8521 /* Release */ = {
400
421
  isa = XCBuildConfiguration;
401
422
  buildSettings = {
423
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
402
424
  CLANG_ENABLE_MODULES = YES;
425
+ CODE_SIGN_IDENTITY = "";
403
426
  DEFINES_MODULE = YES;
404
427
  DYLIB_COMPATIBILITY_VERSION = 1;
405
428
  DYLIB_CURRENT_VERSION = 1;
406
429
  DYLIB_INSTALL_NAME_BASE = "@rpath";
407
- EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
408
430
  FRAMEWORK_SEARCH_PATHS = (
409
431
  "$(inherited)",
410
432
  "$(SDKROOT)/../../Library/Frameworks/",
@@ -483,7 +505,7 @@
483
505
  /* End XCBuildConfiguration section */
484
506
 
485
507
  /* Begin XCConfigurationList section */
486
- F60C68B41B8D038300CC8521 /* Build configuration list for PBXProject "toolc" */ = {
508
+ F60C68B41B8D038300CC8521 /* Build configuration list for PBXProject "TestDumper" */ = {
487
509
  isa = XCConfigurationList;
488
510
  buildConfigurations = (
489
511
  F60C68CE1B8D038300CC8521 /* Debug */,
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <Scheme
3
- LastUpgradeVersion = "0800"
3
+ LastUpgradeVersion = "1010"
4
4
  version = "1.3">
5
5
  <BuildAction
6
6
  parallelizeBuildables = "YES"
@@ -7,13 +7,9 @@
7
7
  //
8
8
 
9
9
  @import Dispatch;
10
+ @import Foundation;
10
11
  @import XCTest;
11
12
 
12
-
13
-
14
-
15
- @class NSSet, NSString, NSURL, NSUUID;
16
-
17
13
  @interface XCTestConfiguration : NSObject <NSSecureCoding>
18
14
  {
19
15
  NSURL *_testBundleURL;
@@ -71,6 +67,46 @@
71
67
 
72
68
  #include <dlfcn.h>
73
69
 
70
+ // Logging
71
+ FILE *logFile;
72
+
73
+ void initializeLogFile(const char *logFilePath)
74
+ {
75
+ logFile = fopen(logFilePath, "w");
76
+ }
77
+
78
+ void logDebug(NSString *, ...) NS_FORMAT_FUNCTION(1, 2);
79
+ void logDebug(NSString *msg, ...)
80
+ {
81
+ assert(logFile);
82
+ va_list varargs;
83
+ va_start(varargs, msg);
84
+ msg = [[NSString alloc] initWithFormat:msg arguments:varargs];
85
+ va_end(varargs);
86
+ fprintf(logFile, "%s\n", msg.UTF8String);
87
+
88
+ NSLog(@"%@", msg);
89
+ }
90
+
91
+ void logInit()
92
+ {
93
+ logDebug(@"Starting TestDumper...");
94
+ logDebug(@"Environment Variables:");
95
+ logDebug(@"%@", NSProcessInfo.processInfo.environment.description);
96
+ logDebug(@"Command Line Arguments:");
97
+ logDebug(@"%@", NSProcessInfo.processInfo.arguments.description);
98
+
99
+ logDebug(@"--------------------------------");
100
+ }
101
+
102
+ OS_NORETURN
103
+ void logEnd(Boolean success)
104
+ {
105
+ int exitCode = success ? EXIT_SUCCESS : EXIT_FAILURE;
106
+ logDebug(@"EndingTestDumper...\nExiting with status %d", exitCode);
107
+ fclose(logFile);
108
+ exit(exitCode);
109
+ }
74
110
 
75
111
  // Used for a structured log, just like Xctool's.
76
112
  // Example: https://github.com/square/xcknife/blob/master/example/xcknife-exemplar.json-stream
@@ -81,10 +117,10 @@ static void PrintJSON(FILE *outFile, id JSONObject)
81
117
 
82
118
  if (error) {
83
119
  fprintf(outFile, "{ \"message\" : \"Error while serializing to JSON. Check out simulator logs for details\" }");
84
- NSLog(@"ERROR: Error generating JSON for object: %s: %s\n",
120
+ logDebug(@"ERROR: Error generating JSON for object: %s: %s\n",
85
121
  [[JSONObject description] UTF8String],
86
122
  [[error localizedFailureReason] UTF8String]);
87
- exit(1);
123
+ logEnd(false);
88
124
  }
89
125
 
90
126
  fwrite([data bytes], 1, [data length], outFile);
@@ -114,51 +150,60 @@ static void PrintTestClass(FILE *outFile, NSString *testClass) {
114
150
  @"totalDuration" : @"0"});
115
151
  }
116
152
 
117
- void enumerateTests();
153
+ void enumerateTests(NSString *);
118
154
 
119
155
  const int TEST_TARGET_LEVEL = 0;
120
156
  const int TEST_CLASS_LEVEL = 1;
121
157
  const int TEST_METHOD_LEVEL = 2;
122
-
158
+ FILE *noteFile;
123
159
 
124
160
  __attribute__((constructor))
125
161
  void initialize() {
126
- NSString *testType = [NSString stringWithUTF8String: getenv("XCTEST_TYPE")];
162
+ NSLog(@"Starting TestDumper");
163
+ const char *logFilePath = [[[NSProcessInfo processInfo] arguments][3] UTF8String];
164
+ initializeLogFile(logFilePath);
165
+ logInit();
166
+ NSString *testBundlePath = [[NSProcessInfo processInfo] arguments][4];
167
+ NSString *testDumperOutputPath = NSProcessInfo.processInfo.environment[@"TestDumperOutputPath"];
168
+ NSFileManager *fileManager = [NSFileManager defaultManager];
127
169
 
170
+ if ([fileManager fileExistsAtPath:testDumperOutputPath]) {
171
+ logDebug(@"File already exists %@. Stopping", testDumperOutputPath);
172
+ logEnd(true);
173
+ }
174
+
175
+ NSString *testType = [NSString stringWithUTF8String: getenv("XCTEST_TYPE")];
128
176
  if ([testType isEqualToString: @"APPTEST"]) {
129
177
  [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
130
- enumerateTests();
178
+ enumerateTests(testBundlePath);
131
179
  }];
132
180
  } else {
133
- enumerateTests();
181
+ enumerateTests(testBundlePath);
134
182
  }
135
183
  }
136
184
 
137
-
138
- void enumerateTests() {
139
- XCTestConfiguration *config = [[XCTestConfiguration alloc] init];
140
- NSString *testType = [NSString stringWithUTF8String: getenv("XCTEST_TYPE")];
141
- NSString *testTarget = [NSString stringWithUTF8String: getenv("XCTEST_TARGET")];
142
-
143
- if ([testType isEqualToString: @"APPTEST"]) {
144
- config.testBundleURL = [NSURL fileURLWithPath:NSProcessInfo.processInfo.environment[@"XCInjectBundle"]];
145
- config.targetApplicationPath = NSProcessInfo.processInfo.environment[@"XCInjectBundleInto"];
146
-
147
- NSString *configPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%ul.xctestconfiguration", arc4random()]];
148
-
149
- NSLog(@"Writing config to %@", configPath);
150
-
151
- NSData *data = [NSKeyedArchiver archivedDataWithRootObject:config];
152
-
153
- [data writeToFile:configPath atomically:true];
154
-
155
- setenv("XCTestConfigurationFilePath", configPath.UTF8String, YES);
156
-
157
- dlopen(getenv("IDE_INJECTION_PATH"), RTLD_GLOBAL);
185
+ void enumerateTests(NSString *testBundlePath) {
186
+ logDebug(@"Listing all test bundles");
187
+ for (NSBundle *bundle in NSBundle.allBundles) {
188
+ logDebug(@"Found a test bundle named: %@", bundle.bundlePath);
158
189
  }
159
- NSString *testBundle = [[[NSProcessInfo processInfo] arguments] lastObject];
160
- [[NSBundle bundleWithPath:testBundle] load];
161
-
190
+ logDebug(@"Finished listing all test bundles");
191
+
192
+ NSBundle* testBundleObj = [NSBundle bundleWithPath:testBundlePath];
193
+ [testBundleObj load];
194
+ logDebug(@"test bundle loaded");
195
+
196
+ logDebug(@"Listing all test bundles");
197
+ for (NSBundle *bundle in NSBundle.allBundles) {
198
+ logDebug(@"Found a test bundle named: %@", bundle.bundlePath);
199
+ }
200
+ logDebug(@"Finished listing all test bundles");
201
+
202
+ NSString *testType = [NSString stringWithUTF8String: getenv("XCTEST_TYPE")];
203
+ NSString *testTarget = [[[testBundlePath componentsSeparatedByString:@"/"] lastObject] componentsSeparatedByString:@"."][0];
204
+
205
+ logDebug(@"The test target is: %@ of type %@", testTarget, testType);
206
+
162
207
  FILE *outFile;
163
208
  NSString *testDumperOutputPath = NSProcessInfo.processInfo.environment[@"TestDumperOutputPath"];
164
209
 
@@ -168,13 +213,18 @@ void enumerateTests() {
168
213
  outFile = fopen(testDumperOutputPath.UTF8String, "w+");
169
214
  }
170
215
 
171
- NSLog(@"Opened %@ with fd %p", testDumperOutputPath, outFile);
172
-
216
+ logDebug(@"Opened %@ with fd %p", testDumperOutputPath, outFile);
217
+ if (outFile == NULL) {
218
+ logDebug(@"File already exists at %@. Stopping", testDumperOutputPath);
219
+ logEnd(true);
220
+ }
221
+
173
222
  PrintDumpStart(outFile, testType);
174
- [[XCTestSuite defaultTestSuite] printTestsWithLevel:0 withTarget: testTarget withParent: nil outputFile:outFile];
223
+ XCTestSuite* testSuite = [XCTestSuite defaultTestSuite];
224
+ [testSuite printTestsWithLevel:0 withTarget: testTarget withParent: nil outputFile:outFile];
175
225
  PrintDumpEnd(outFile, testType);
176
226
  fclose(outFile);
177
- exit(0);
227
+ logEnd(true);
178
228
  }
179
229
 
180
230
 
@@ -193,8 +243,11 @@ void enumerateTests() {
193
243
  case TEST_METHOD_LEVEL:
194
244
  PrintTestClass(outputFile, parent);
195
245
  break;
246
+ case TEST_CLASS_LEVEL:
247
+ // nothing to do here
248
+ break;
196
249
  default:
197
- NSLog(@"Uknown level %ld", level);
250
+ logDebug(@"Unknown test level %ld for test %@", level, t.debugDescription);
198
251
 
199
252
  }
200
253
  if (level == TEST_METHOD_LEVEL) {