├── .gitignore ├── .travis.yml ├── README.md ├── bin └── ocunit2junit ├── example.png ├── ocunit2junit.gemspec └── test ├── TestProject ├── TestProject.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── TestProject.xcscheme ├── TestProject │ ├── TestProject-Prefix.pch │ ├── TestProject.1 │ └── main.m └── TestProjectTests │ ├── TestProjectTests-Info.plist │ ├── TestProjectTests-Prefix.pch │ ├── TestProjectTests.m │ └── en.lproj │ └── InfoPlist.strings └── test_basic.rb /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # OCUnit2JUnit output 5 | test-reports 6 | 7 | # Xcode 8 | build/ 9 | *.pbxuser 10 | !default.pbxuser 11 | *.mode1v3 12 | !default.mode1v3 13 | *.mode2v3 14 | !default.mode2v3 15 | *.perspectivev3 16 | !default.perspectivev3 17 | *.xcworkspace 18 | !default.xcworkspace 19 | xcuserdata 20 | profile 21 | *.moved-aside 22 | DerivedData 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: ruby test/test_basic.rb 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ABANDONWARE! 2 | 3 | This script is no longer maintained! Have a look at one of the many forks or look for alternatives. Thanks for all the fish! 🐟 4 | 5 | Introduction 6 | ====================== 7 | 8 | OCUnit2JUnit is a script that converts output from OCUnit or [Kiwi](https://github.com/allending/Kiwi) to the format used by JUnit. The main purpose is to be able to parse output from Objective-C (OCUnit) test cases on a Java-based build server, such as [Jenkins](http://jenkins-ci.org/). 9 | 10 | 11 | Installation 12 | ====================== 13 | 14 | * Install with 'gem install ocunit2junit' (possibly prepended by 'sudo' if your Ruby installation requires that) 15 | 16 | 17 | Usage 18 | ====================== 19 | 20 | * Make sure your build server can access the xcodebuild executable 21 | * Use this shell command to build: 22 | 23 | `xcodebuild -target -sdk -configuration 2>&1 | ocunit2junit` 24 | 25 | * The output is, by default, in the `test-reports` folder 26 | * If your build fails, this script will pass the error code 27 | * All output is also passed along, so you will still see everything in your build log 28 | 29 | 30 | Kiwi 31 | ====================== 32 | 33 | This script also generates human readable test results for [Kiwi BDD Testing Framework](https://github.com/allending/Kiwi): 34 | 35 | ![Example output](https://github.com/MattesGroeger/OCUnit2JUnit/raw/master/example.png "Example output") 36 | 37 | However, if you don't want this, you can disable it in the header: 38 | 39 | SUPPORT_KIWI = false 40 | 41 | 42 | More information 43 | ====================== 44 | 45 | * If you're having issues with character encoding, please upgrade to Ruby 1.9.2 or later. 46 | * More info can be found in [this blog post](http://blog.jayway.com/2010/01/31/continuos-integration-for-xcode-projects/). 47 | 48 | 49 | Licence 50 | ====================== 51 | 52 | Free to use however you want. 53 | 54 | 55 | Author 56 | ====================== 57 | 58 | OCUnit2JUnit was created by Christian Hedin. 59 | Twitter: @ciryon 60 | Google Plus: https://plus.google.com/103286810504956788514/ 61 | -------------------------------------------------------------------------------- /bin/ocunit2junit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # ocunit2junit.rb was written by Christian Hedin 4 | # Version: 0.1 - 30/01 2010 5 | # Usage: 6 | # xcodebuild -yoursettings | ocunit2junit.rb 7 | # All output is just passed through to stdout so you don't miss a thing! 8 | # JUnit style XML-report are put in the folder specified below. 9 | # 10 | # Known problems: 11 | # * "Errors" are not cought, only "warnings". 12 | # * It's not possible to click links to failed test in Hudson 13 | # * It's not possible to browse the source code in Hudson 14 | # 15 | # Acknowledgement: 16 | # Big thanks to Steen Lehmann for prettifying this script. 17 | ################################################################ 18 | # Edit these variables to match your system 19 | # 20 | # 21 | # Where to put the XML-files from your unit tests 22 | TEST_REPORTS_FOLDER = ENV.has_key?('TEST_REPORTS_FOLDER') ? ENV['TEST_REPORTS_FOLDER'] : "test-reports" 23 | SUPPORT_KIWI = ENV.has_key?('SUPPORT_KIWI') ? ENV['SUPPORT_KIWI'] : true 24 | # 25 | # 26 | # Don't edit below this line 27 | ################################################################ 28 | 29 | require 'time' 30 | require 'fileutils' 31 | require 'socket' 32 | 33 | class ReportParser 34 | 35 | attr_reader :exit_code 36 | 37 | def initialize(piped_input) 38 | @piped_input = piped_input 39 | @exit_code = 0 40 | 41 | FileUtils.rm_rf(TEST_REPORTS_FOLDER) 42 | FileUtils.mkdir_p(TEST_REPORTS_FOLDER) 43 | parse_input 44 | end 45 | 46 | private 47 | 48 | def parse_input 49 | if @piped_input.respond_to?(:each) 50 | line_enumerator = @piped_input.each 51 | elsif @piped_input.respond_to?(:each_line) 52 | line_enumerator = @piped_input.each_line 53 | end 54 | 55 | line_enumerator.each do |piped_row| 56 | if piped_row.respond_to?("encode!") 57 | temporary_encoding = (RUBY_VERSION == '1.9.2') ? 'UTF-8' : 'UTF-16' 58 | piped_row.encode!(temporary_encoding, 'UTF-8', :invalid => :replace, :replace => '') 59 | piped_row.encode!('UTF-8', temporary_encoding) 60 | end 61 | puts piped_row 62 | 63 | description_results = piped_row.scan(/\s\'(.+)\'\s/) 64 | if description_results && description_results[0] && description_results[0] 65 | description = description_results[0][0] 66 | end 67 | 68 | case piped_row 69 | 70 | when /Test Suite '(\S+)'.*started at\s+(.*)/ 71 | t = Time.parse($2.to_s) 72 | handle_start_test_suite(t) 73 | @last_description = nil 74 | @current_suite = $1 75 | 76 | when /Test Suite '(\S+)'.*finished at\s+(.*)./ 77 | t = Time.parse($2.to_s) 78 | handle_end_test_suite($1,t) 79 | 80 | when /Test Suite '(\S+)'.*passed at\s+(.*)./ 81 | t = Time.parse($2.to_s) 82 | handle_end_test_suite($1,t) 83 | 84 | when /Test Suite '(\S+)'.*failed at\s+(.*)./ 85 | t = Time.parse($2.to_s) 86 | handle_end_test_suite($1,t) 87 | 88 | when /Test Case '-\[\S+\s+(\S+)\]' started./ 89 | test_case = $1 90 | @current_test_case = $1 91 | @last_description = nil 92 | @current_test = test_case 93 | 94 | when /Test Case '-\[\S+\s+(\S+)\]' passed \((.*) seconds\)/ 95 | test_case = get_test_case_name($1, @last_description) 96 | test_case_duration = $2.to_f 97 | handle_test_passed(test_case,test_case_duration) 98 | 99 | when /Restarting after unexpected exit or crash in (\S+)\// 100 | error_message = "Crash encountered during the test!" 101 | test_case = @current_test 102 | test_suite = @current_suite 103 | handle_test_error(test_suite,test_case,error_message, "Search the logs for error location!") 104 | #no way to know the time elapsed in this case as XCUnit does not print it in the informational message. 105 | handle_test_failed(test_case, 0.000) 106 | 107 | #mark current suite as restarting. 108 | @restarting_current_suite = true 109 | 110 | when /(.*): error: -\[(\S+) (\S+)\] : (.*)/ 111 | error_location = $1 112 | test_suite = $2 113 | error_message = $4 114 | test_case = get_test_case_name($3, description) 115 | handle_test_error(test_suite,test_case,error_message,error_location) 116 | 117 | when /Assertion Failure: (.*):(.*): (.*)/ 118 | error_location = $1 119 | test_suite = $1 120 | 121 | test_case = @current_test_case 122 | 123 | error_message = $3 124 | handle_test_error(test_suite,test_case,error_message,error_location) 125 | 126 | when /Test Case '-\[\S+ (\S+)\]' failed \((\S+) seconds\)/ 127 | test_case = get_test_case_name($1, @last_description) 128 | test_case_duration = $2.to_f 129 | handle_test_failed(test_case,test_case_duration) 130 | 131 | when /failed with exit code (\d+)/ 132 | @exit_code = $1.to_i 133 | 134 | when 135 | /BUILD FAILED/ 136 | @exit_code = -1; 137 | end 138 | 139 | if description 140 | @last_description = description 141 | end 142 | end 143 | end 144 | 145 | def handle_start_test_suite(start_time) 146 | 147 | #if we detected that XCUinit says it is being restarted because of an unexpected interruption. (i.e. a crash) 148 | #In this case, we don't want to treat it as a "newly" encountered suite. 149 | return if @restarting_current_suite 150 | 151 | @total_failed_test_cases = 0 152 | @total_passed_test_cases = 0 153 | @tests_results = Hash.new # test_case -> duration 154 | @errors = Hash.new # test_case -> error_msg 155 | @ended_current_test_suite = false 156 | @cur_start_time = start_time 157 | @current_test_case = "none" 158 | end 159 | 160 | def handle_end_test_suite(test_name,end_time) 161 | unless @ended_current_test_suite 162 | current_file = File.open("#{TEST_REPORTS_FOLDER}/TEST-#{test_name}.xml", 'w') 163 | host_name = string_to_xml Socket.gethostname 164 | test_name = string_to_xml test_name 165 | test_duration = (end_time - @cur_start_time).to_s 166 | total_tests = @total_failed_test_cases + @total_passed_test_cases 167 | suite_info = '' 168 | current_file << "\n" 169 | current_file << suite_info 170 | @tests_results.each do |t| 171 | test_case = string_to_xml t[0] 172 | duration = @tests_results[test_case] 173 | current_file << "\n" 184 | current_file << "#{location}\n" 185 | current_file << "\n" 186 | else 187 | current_file << " />\n" 188 | end 189 | end 190 | current_file << "\n" 191 | current_file.close 192 | @ended_current_test_suite = true 193 | @restarting_current_suite = false 194 | end 195 | end 196 | 197 | def string_to_xml(s) 198 | s.gsub(/&/, '&').gsub(/'/, '"').gsub(/"; }; 35 | 492FBE0815CECD7B00878766 /* TestProject-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestProject-Prefix.pch"; sourceTree = ""; }; 36 | 492FBE0915CECD7B00878766 /* TestProject.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = TestProject.1; sourceTree = ""; }; 37 | 492FBE1515CECD9800878766 /* TestProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 492FBE1815CECD9800878766 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; 39 | 492FBE1B15CECD9800878766 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 40 | 492FBE1C15CECD9800878766 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 41 | 492FBE1D15CECD9800878766 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | 492FBE2015CECD9800878766 /* TestProjectTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TestProjectTests-Info.plist"; sourceTree = ""; }; 43 | 492FBE2215CECD9800878766 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 44 | 492FBE2515CECD9800878766 /* TestProjectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestProjectTests.m; sourceTree = ""; }; 45 | 492FBE2715CECD9800878766 /* TestProjectTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TestProjectTests-Prefix.pch"; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 492FBDFB15CECD7B00878766 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 492FBE0315CECD7B00878766 /* Foundation.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | 492FBE1115CECD9800878766 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 492FBE1915CECD9800878766 /* Cocoa.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 492FBDF315CECD7B00878766 = { 69 | isa = PBXGroup; 70 | children = ( 71 | 492FBE0415CECD7B00878766 /* TestProject */, 72 | 492FBE1E15CECD9800878766 /* TestProjectTests */, 73 | 492FBE0115CECD7B00878766 /* Frameworks */, 74 | 492FBDFF15CECD7B00878766 /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 492FBDFF15CECD7B00878766 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 492FBDFE15CECD7B00878766 /* TestProject */, 82 | 492FBE1515CECD9800878766 /* TestProjectTests.xctest */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 492FBE0115CECD7B00878766 /* Frameworks */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 492FBE0215CECD7B00878766 /* Foundation.framework */, 91 | 492FBE1815CECD9800878766 /* Cocoa.framework */, 92 | 492FBE1A15CECD9800878766 /* Other Frameworks */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | 492FBE0415CECD7B00878766 /* TestProject */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 492FBE0515CECD7B00878766 /* main.m */, 101 | 492FBE0915CECD7B00878766 /* TestProject.1 */, 102 | 492FBE0715CECD7B00878766 /* Supporting Files */, 103 | ); 104 | path = TestProject; 105 | sourceTree = ""; 106 | }; 107 | 492FBE0715CECD7B00878766 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 492FBE0815CECD7B00878766 /* TestProject-Prefix.pch */, 111 | ); 112 | name = "Supporting Files"; 113 | sourceTree = ""; 114 | }; 115 | 492FBE1A15CECD9800878766 /* Other Frameworks */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 492FBE1B15CECD9800878766 /* AppKit.framework */, 119 | 492FBE1C15CECD9800878766 /* CoreData.framework */, 120 | 492FBE1D15CECD9800878766 /* Foundation.framework */, 121 | ); 122 | name = "Other Frameworks"; 123 | sourceTree = ""; 124 | }; 125 | 492FBE1E15CECD9800878766 /* TestProjectTests */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 492FBE2515CECD9800878766 /* TestProjectTests.m */, 129 | 492FBE1F15CECD9800878766 /* Supporting Files */, 130 | ); 131 | path = TestProjectTests; 132 | sourceTree = ""; 133 | }; 134 | 492FBE1F15CECD9800878766 /* Supporting Files */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 492FBE2015CECD9800878766 /* TestProjectTests-Info.plist */, 138 | 492FBE2115CECD9800878766 /* InfoPlist.strings */, 139 | 492FBE2715CECD9800878766 /* TestProjectTests-Prefix.pch */, 140 | ); 141 | name = "Supporting Files"; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | 492FBDFD15CECD7B00878766 /* TestProject */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 492FBE0D15CECD7B00878766 /* Build configuration list for PBXNativeTarget "TestProject" */; 150 | buildPhases = ( 151 | 492FBDFA15CECD7B00878766 /* Sources */, 152 | 492FBDFB15CECD7B00878766 /* Frameworks */, 153 | 492FBDFC15CECD7B00878766 /* CopyFiles */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = TestProject; 160 | productName = TestProject; 161 | productReference = 492FBDFE15CECD7B00878766 /* TestProject */; 162 | productType = "com.apple.product-type.tool"; 163 | }; 164 | 492FBE1415CECD9800878766 /* TestProjectTests */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 492FBE2815CECD9800878766 /* Build configuration list for PBXNativeTarget "TestProjectTests" */; 167 | buildPhases = ( 168 | 492FBE1015CECD9800878766 /* Sources */, 169 | 492FBE1115CECD9800878766 /* Frameworks */, 170 | 492FBE1215CECD9800878766 /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = TestProjectTests; 177 | productName = TestProjectTests; 178 | productReference = 492FBE1515CECD9800878766 /* TestProjectTests.xctest */; 179 | productType = "com.apple.product-type.bundle.unit-test"; 180 | }; 181 | /* End PBXNativeTarget section */ 182 | 183 | /* Begin PBXProject section */ 184 | 492FBDF515CECD7B00878766 /* Project object */ = { 185 | isa = PBXProject; 186 | attributes = { 187 | LastTestingUpgradeCheck = 0720; 188 | LastUpgradeCheck = 0940; 189 | }; 190 | buildConfigurationList = 492FBDF815CECD7B00878766 /* Build configuration list for PBXProject "TestProject" */; 191 | compatibilityVersion = "Xcode 3.2"; 192 | developmentRegion = English; 193 | hasScannedForEncodings = 0; 194 | knownRegions = ( 195 | en, 196 | ); 197 | mainGroup = 492FBDF315CECD7B00878766; 198 | productRefGroup = 492FBDFF15CECD7B00878766 /* Products */; 199 | projectDirPath = ""; 200 | projectRoot = ""; 201 | targets = ( 202 | 492FBDFD15CECD7B00878766 /* TestProject */, 203 | 492FBE1415CECD9800878766 /* TestProjectTests */, 204 | ); 205 | }; 206 | /* End PBXProject section */ 207 | 208 | /* Begin PBXResourcesBuildPhase section */ 209 | 492FBE1215CECD9800878766 /* Resources */ = { 210 | isa = PBXResourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 492FBE2315CECD9800878766 /* InfoPlist.strings in Resources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | /* End PBXResourcesBuildPhase section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | 492FBDFA15CECD7B00878766 /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | 492FBE0615CECD7B00878766 /* main.m in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | 492FBE1015CECD9800878766 /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | 492FBE2615CECD9800878766 /* TestProjectTests.m in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | /* End PBXSourcesBuildPhase section */ 237 | 238 | /* Begin PBXVariantGroup section */ 239 | 492FBE2115CECD9800878766 /* InfoPlist.strings */ = { 240 | isa = PBXVariantGroup; 241 | children = ( 242 | 492FBE2215CECD9800878766 /* en */, 243 | ); 244 | name = InfoPlist.strings; 245 | sourceTree = ""; 246 | }; 247 | /* End PBXVariantGroup section */ 248 | 249 | /* Begin XCBuildConfiguration section */ 250 | 492FBE0B15CECD7B00878766 /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_ENABLE_OBJC_ARC = YES; 256 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_COMMA = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INFINITE_RECURSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 266 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 267 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 268 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 269 | CLANG_WARN_STRICT_PROTOTYPES = YES; 270 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | COPY_PHASE_STRIP = NO; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | ENABLE_TESTABILITY = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_DYNAMIC_NO_PIC = NO; 278 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_OPTIMIZATION_LEVEL = 0; 281 | GCC_PREPROCESSOR_DEFINITIONS = ( 282 | "DEBUG=1", 283 | "$(inherited)", 284 | ); 285 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | MACOSX_DEPLOYMENT_TARGET = 10.8; 293 | ONLY_ACTIVE_ARCH = YES; 294 | SDKROOT = macosx; 295 | }; 296 | name = Debug; 297 | }; 298 | 492FBE0C15CECD7B00878766 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ALWAYS_SEARCH_USER_PATHS = NO; 302 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 305 | CLANG_WARN_BOOL_CONVERSION = YES; 306 | CLANG_WARN_COMMA = YES; 307 | CLANG_WARN_CONSTANT_CONVERSION = YES; 308 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 309 | CLANG_WARN_EMPTY_BODY = YES; 310 | CLANG_WARN_ENUM_CONVERSION = YES; 311 | CLANG_WARN_INFINITE_RECURSION = YES; 312 | CLANG_WARN_INT_CONVERSION = YES; 313 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 314 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 316 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 317 | CLANG_WARN_STRICT_PROTOTYPES = YES; 318 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 319 | CLANG_WARN_UNREACHABLE_CODE = YES; 320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 321 | COPY_PHASE_STRIP = YES; 322 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 326 | GCC_NO_COMMON_BLOCKS = YES; 327 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 328 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 329 | GCC_WARN_UNDECLARED_SELECTOR = YES; 330 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 331 | GCC_WARN_UNUSED_FUNCTION = YES; 332 | GCC_WARN_UNUSED_VARIABLE = YES; 333 | MACOSX_DEPLOYMENT_TARGET = 10.8; 334 | SDKROOT = macosx; 335 | }; 336 | name = Release; 337 | }; 338 | 492FBE0E15CECD7B00878766 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 342 | GCC_PREFIX_HEADER = "TestProject/TestProject-Prefix.pch"; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | }; 345 | name = Debug; 346 | }; 347 | 492FBE0F15CECD7B00878766 /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 351 | GCC_PREFIX_HEADER = "TestProject/TestProject-Prefix.pch"; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | }; 354 | name = Release; 355 | }; 356 | 492FBE2915CECD9800878766 /* Debug */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | COMBINE_HIDPI_IMAGES = YES; 360 | FRAMEWORK_SEARCH_PATHS = ( 361 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 362 | "$(inherited)", 363 | ); 364 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 365 | GCC_PREFIX_HEADER = "TestProjectTests/TestProjectTests-Prefix.pch"; 366 | INFOPLIST_FILE = "TestProjectTests/TestProjectTests-Info.plist"; 367 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.ocunit2junit.${PRODUCT_NAME:rfc1034identifier}"; 368 | PRODUCT_NAME = "$(TARGET_NAME)"; 369 | }; 370 | name = Debug; 371 | }; 372 | 492FBE2A15CECD9800878766 /* Release */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | COMBINE_HIDPI_IMAGES = YES; 376 | FRAMEWORK_SEARCH_PATHS = ( 377 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 378 | "$(inherited)", 379 | ); 380 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 381 | GCC_PREFIX_HEADER = "TestProjectTests/TestProjectTests-Prefix.pch"; 382 | INFOPLIST_FILE = "TestProjectTests/TestProjectTests-Info.plist"; 383 | PRODUCT_BUNDLE_IDENTIFIER = "com.github.ocunit2junit.${PRODUCT_NAME:rfc1034identifier}"; 384 | PRODUCT_NAME = "$(TARGET_NAME)"; 385 | }; 386 | name = Release; 387 | }; 388 | /* End XCBuildConfiguration section */ 389 | 390 | /* Begin XCConfigurationList section */ 391 | 492FBDF815CECD7B00878766 /* Build configuration list for PBXProject "TestProject" */ = { 392 | isa = XCConfigurationList; 393 | buildConfigurations = ( 394 | 492FBE0B15CECD7B00878766 /* Debug */, 395 | 492FBE0C15CECD7B00878766 /* Release */, 396 | ); 397 | defaultConfigurationIsVisible = 0; 398 | defaultConfigurationName = Release; 399 | }; 400 | 492FBE0D15CECD7B00878766 /* Build configuration list for PBXNativeTarget "TestProject" */ = { 401 | isa = XCConfigurationList; 402 | buildConfigurations = ( 403 | 492FBE0E15CECD7B00878766 /* Debug */, 404 | 492FBE0F15CECD7B00878766 /* Release */, 405 | ); 406 | defaultConfigurationIsVisible = 0; 407 | defaultConfigurationName = Release; 408 | }; 409 | 492FBE2815CECD9800878766 /* Build configuration list for PBXNativeTarget "TestProjectTests" */ = { 410 | isa = XCConfigurationList; 411 | buildConfigurations = ( 412 | 492FBE2915CECD9800878766 /* Debug */, 413 | 492FBE2A15CECD9800878766 /* Release */, 414 | ); 415 | defaultConfigurationIsVisible = 0; 416 | defaultConfigurationName = Release; 417 | }; 418 | /* End XCConfigurationList section */ 419 | }; 420 | rootObject = 492FBDF515CECD7B00878766 /* Project object */; 421 | } 422 | -------------------------------------------------------------------------------- /test/TestProject/TestProject.xcodeproj/xcshareddata/xcschemes/TestProject.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /test/TestProject/TestProject/TestProject-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TestProject' target in the 'TestProject' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /test/TestProject/TestProject/TestProject.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd 8/5/12 \" DATE 7 | .Dt TestProject 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm TestProject, 11 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 12 | .\" words here as the database is built based on the words here and in the .ND line. 13 | .Nm Other_name_for_same_program(), 14 | .Nm Yet another name for the same program. 15 | .\" Use .Nm macro to designate other names for the documented program. 16 | .Nd This line parsed for whatis database. 17 | .Sh SYNOPSIS \" Section Header - required - don't modify 18 | .Nm 19 | .Op Fl abcd \" [-abcd] 20 | .Op Fl a Ar path \" [-a path] 21 | .Op Ar file \" [file] 22 | .Op Ar \" [file ...] 23 | .Ar arg0 \" Underlined argument - use .Ar anywhere to underline 24 | arg2 ... \" Arguments 25 | .Sh DESCRIPTION \" Section Header - required - don't modify 26 | Use the .Nm macro to refer to your program throughout the man page like such: 27 | .Nm 28 | Underlining is accomplished with the .Ar macro like this: 29 | .Ar underlined text . 30 | .Pp \" Inserts a space 31 | A list of items with descriptions: 32 | .Bl -tag -width -indent \" Begins a tagged list 33 | .It item a \" Each item preceded by .It macro 34 | Description of item a 35 | .It item b 36 | Description of item b 37 | .El \" Ends the list 38 | .Pp 39 | A list of flags and their descriptions: 40 | .Bl -tag -width -indent \" Differs from above in tag removed 41 | .It Fl a \"-a flag as a list item 42 | Description of -a flag 43 | .It Fl b 44 | Description of -b flag 45 | .El \" Ends the list 46 | .Pp 47 | .\" .Sh ENVIRONMENT \" May not be needed 48 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 49 | .\" .It Ev ENV_VAR_1 50 | .\" Description of ENV_VAR_1 51 | .\" .It Ev ENV_VAR_2 52 | .\" Description of ENV_VAR_2 53 | .\" .El 54 | .Sh FILES \" File used or created by the topic of the man page 55 | .Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact 56 | .It Pa /usr/share/file_name 57 | FILE_1 description 58 | .It Pa /Users/joeuser/Library/really_long_file_name 59 | FILE_2 description 60 | .El \" Ends the list 61 | .\" .Sh DIAGNOSTICS \" May not be needed 62 | .\" .Bl -diag 63 | .\" .It Diagnostic Tag 64 | .\" Diagnostic informtion here. 65 | .\" .It Diagnostic Tag 66 | .\" Diagnostic informtion here. 67 | .\" .El 68 | .Sh SEE ALSO 69 | .\" List links in ascending order by section, alphabetically within a section. 70 | .\" Please do not reference files that do not exist without filing a bug report 71 | .Xr a 1 , 72 | .Xr b 1 , 73 | .Xr c 1 , 74 | .Xr a 2 , 75 | .Xr b 2 , 76 | .Xr a 3 , 77 | .Xr b 3 78 | .\" .Sh BUGS \" Document known, unremedied bugs 79 | .\" .Sh HISTORY \" Document history if command behaves in a unique manner -------------------------------------------------------------------------------- /test/TestProject/TestProject/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, const char * argv[]) 4 | { 5 | 6 | @autoreleasepool { 7 | 8 | // insert code here... 9 | NSLog(@"Hello, World!"); 10 | 11 | } 12 | return 0; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /test/TestProject/TestProjectTests/TestProjectTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/TestProject/TestProjectTests/TestProjectTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'TestProjectTests' target in the 'TestProjectTests' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /test/TestProject/TestProjectTests/TestProjectTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface TestProjectTests : XCTestCase 4 | @end 5 | 6 | @implementation TestProjectTests 7 | 8 | - (void)testSuccess 9 | { 10 | XCTAssertEqual(2 + 2, 4, @"Arithmetic FTW"); 11 | } 12 | 13 | - (void)testFail 14 | { 15 | XCTFail(@"It's easy to write failing tests"); 16 | XCTFail(@"Some tests have multiple failures"); 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /test/TestProject/TestProjectTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /test/test_basic.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | 3 | require 'fileutils' 4 | require 'rexml/document' 5 | 6 | class BasicTests < Test::Unit::TestCase 7 | 8 | def setup 9 | Helper.setup_test_directory 10 | end 11 | 12 | def teardown 13 | Helper.teardown_test_directory 14 | end 15 | 16 | def test_output_to_reports_dir 17 | Helper.pipe_xcodebuild_to_ocunit2junit 18 | 19 | assert File.directory?(Helper.test_reports_output_path), 20 | "Test reports should be written to a 'test-reports' directory" 21 | 22 | assert File.exists?(Helper.test_reports_output_path + '/TEST-TestProjectTests.xml'), 23 | "The TestProject should be parsed in a TEST-TestProjectTests.xml report" 24 | end 25 | 26 | def test_output_log_to_reports_dir 27 | Helper.pipe_xcodebuild_log_to_ocunit2junit 28 | 29 | assert File.directory?(Helper.test_reports_output_path), 30 | "Test reports driven from a log should be written to a 'test-reports' directory" 31 | end 32 | 33 | def test_report_content 34 | Helper.pipe_xcodebuild_to_ocunit2junit 35 | file = File.new Helper.test_reports_output_path + '/TEST-TestProjectTests.xml' 36 | report = REXML::Document.new file 37 | 38 | assert !report.elements.empty?, 39 | "The TEST-TestProjectTests.xml test report shouldn't be empty" 40 | 41 | assert report.root.elements.size == 2, 42 | "The TEST-TestProjectTests.xml report should have two elements" 43 | 44 | assert report.root.elements['//failure'].size == 1, 45 | "The TEST-TestProjectTests.xml report should have one element" 46 | 47 | assert_equal 'failed - It"s easy to write failing tests', 48 | report.root.elements['//failure'].attribute('message').to_s, 49 | "The TEST-TestProjectTests.xml report should include the first failure message" 50 | end 51 | 52 | module Helper 53 | 54 | TEST_PATH = '/tmp/com.github.ocunit2junit.test' 55 | 56 | def self.setup_test_directory 57 | FileUtils.mkpath TEST_PATH 58 | end 59 | 60 | def self.teardown_test_directory 61 | FileUtils.rm_rf TEST_PATH 62 | end 63 | 64 | def self.test_reports_output_path 65 | TEST_PATH + '/test-reports' 66 | end 67 | 68 | def self.pipe_xcodebuild_to_ocunit2junit 69 | abs_file_path = File.expand_path(File.dirname(__FILE__)) 70 | ocunit2junit = abs_file_path + '/../bin/ocunit2junit' 71 | xcodeproj = abs_file_path + '/TestProject/TestProject.xcodeproj' 72 | `pushd #{TEST_PATH}; xcodebuild -project #{xcodeproj} -scheme TestProject test | #{ocunit2junit}; popd` 73 | end 74 | 75 | def self.pipe_xcodebuild_log_to_ocunit2junit 76 | abs_file_path = File.expand_path(File.dirname(__FILE__)) 77 | ocunit2junit = abs_file_path + '/../bin/ocunit2junit' 78 | xcodeproj = abs_file_path + '/TestProject/TestProject.xcodeproj' 79 | outputFile = abs_file_path + 'output.log' 80 | `pushd #{TEST_PATH}; xcodebuild -project #{xcodeproj} -scheme TestProject test > #{outputFile}; cat #{outputFile} | #{ocunit2junit}; popd` 81 | `rm #{outputFile}` 82 | end 83 | 84 | end 85 | 86 | end 87 | --------------------------------------------------------------------------------