Skip to content
Browse files

Merge in siuying:test-reporting

  • Loading branch information...
2 parents e62ecce + 44a5ba9 commit d1f6e094d0220a359462ec4fe2520aff546ca492 @rayh committed Apr 14, 2012
View
178 lib/xcode/test/ocunit_report_parser.rb
@@ -0,0 +1,178 @@
+require 'time'
+require 'fileutils'
+require 'xcode/test/suite_result'
+require 'xcode/test/test_result'
+
+module Xcode
+ module Test
+
+ module Formatters
+ end
+
+ class OCUnitReportParser
+
+ attr_reader :reports, :end_time, :start_timel
+ attr_accessor :debug, :formatters
+
+ def initialize
+ @debug = false
+ @exit_code = 0
+ @reports = []
+ @formatters = []
+ @failed = false
+ @start_time = nil
+ @end_time = nil
+ @unexpected = false
+
+ add_formatter :junit, 'test-reports'
+ add_formatter :stdout
+ end
+
+ def unexpected?
+ @unexpected
+ end
+
+ def succeed?
+ !self.failed?
+ end
+
+ def failed?
+ @failed or @unexpected
+ end
+
+ def finished?
+ !@end_time.nil?
+ end
+
+ def duration
+ return 0 if @start_time.nil?
+ return Time.now - @start_time if @end_time.nil?
+ @end_time - @start_time
+ end
+
+ def add_formatter(format, *args)
+ require "xcode/test/formatters/#{format.to_s}_formatter"
+ formatter = Formatters.const_get("#{format.to_s.capitalize}Formatter").new(*args)
+ @formatters << formatter
+ end
+
+ def flush
+ return if finished?
+
+ # if there is a current, unfinished test - fail it
+ unless current_test.nil? or current_test.passed?
+ fail_current_test(0)
+ @failed = true
+ end
+
+ # if there is a current suite which isnt finished - finish it
+ unless current_suite.nil? or current_suite.finished?
+ @failed = true # It may not have failed, but we want to indicate an unexpected end
+ current_suite.finish
+ notify_formatters(:after_suite, current_suite)
+ end
+
+ # finish all tests
+ @end_time = Time.now
+ notify_formatters(:after, self)
+ end
+
+ def <<(piped_row)
+ puts piped_row if @debug
+
+ case piped_row
+
+ when /Test Suite '(\S+)'.*started at\s+(.*)/
+ name = $1
+ time = Time.parse($2)
+ if name=~/\//
+ # all tests begin
+ @start_time = Time.now
+ notify_formatters(:before, self)
+ else
+ @reports << SuiteResult.new(name, time)
+ notify_formatters(:before_suite, current_suite)
+ end
+
+ when /Test Suite '(\S+)'.*finished at\s+(.*)./
+ time = Time.parse($2)
+ name = $1
+ if name=~/\//
+ # all tests ended
+ @end_time = Time.now
+ notify_formatters(:after, self)
+ else
+ @reports.last.finish(time)
+ notify_formatters(:after_suite, current_suite)
+ end
+
+ when /Test Case '-\[\S+\s+(\S+)\]' started./
+ test = TestResult.new($1, current_suite)
+ @reports.last.tests << test
+ notify_formatters(:before_test, test)
+
+ when /Test Case '-\[\S+\s+(\S+)\]' passed \((.*) seconds\)/
+ @reports.last.tests.last.passed($2.to_f)
+ notify_formatters(:after_test, current_test)
+
+ when /(.*): error: -\[(\S+) (\S+)\] : (.*)/
+ current_test.add_error($4,$1)
+ @failed = true
+ # notify_formatters(:after_test, @reports.last.tests.last)
+
+ when /Test Case '-\[\S+ (\S+)\]' failed \((\S+) seconds\)/
+ fail_current_test($2.to_f)
+ @failed = true
+
+ # when /failed with exit code (\d+)/,
+ when /BUILD FAILED/
+ flush
+
+ when /Segmentation fault/
+ @unexpected=true
+
+ when /Run test case (\w+)/
+ # ignore
+ when /Run test suite (\w+)/
+ # ignore
+ when /Executed (\d+) test, with (\d+) failures \((\d+) unexpected\) in (\S+) \((\S+)\) seconds/
+ # ignore
+ else
+ append_line_to_current_test piped_row
+ end # case
+
+ end # <<
+
+ private
+
+ def notify_formatters(event, obj=nil)
+ @formatters.each do |f|
+ f.send event, obj if f.respond_to? event
+ end
+ end
+
+ def current_suite
+ @reports.last
+ end
+
+ def current_test
+ @reports.last.tests.last unless current_suite.nil?
+ end
+
+ def fail_current_test(duration=0)
+ return if current_test.nil?
+
+ current_test.failed(duration)
+ notify_formatters(:after_test, current_test)
+ end
+
+ def append_line_to_current_test(line)
+ return if current_suite.nil? or !current_suite.end_time.nil?
+ return if current_test.nil?
+ current_test << line
+ end
+
+
+ end # OCUnitReportParser
+ end # Test
+end # Xcode
View
4 lib/xcode/test/report.rb
@@ -43,6 +43,10 @@ def unexpected?
@unexpected
end
+ def succeed?
+ !self.failed?
+ end
+
def failed?
return true if unexpected?
View
9 lib/xcode/workspace.rb
@@ -1,4 +1,5 @@
require 'xcode/project'
+require 'nokogiri'
module Xcode
class Workspace
@@ -11,9 +12,11 @@ def initialize(path)
@projects = []
@path = File.expand_path path
- File.open(@path).read.split(/<FileRef/).each do |line|
- if line=~/location\s*=\s*\"group\:(.+?)\"/
- project_path = "#{workspace_root}/#{$1}"
+ doc = Nokogiri::XML(open(@path))
+ doc.search("FileRef").each do |file|
+ location = file["location"]
+ if matcher = location.match(/^group:(.+)$/)
+ project_path = "#{workspace_root}/#{matcher[1]}"
@projects << Xcode::Project.new(project_path)
end
end
View
7 spec/TestWorkspace2.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<Workspace
+ version = '1.0'>
+ <FileRef
+ location = 'group:TestProject/TestProject.xcodeproj'>
+ </FileRef>
+</Workspace>
View
BIN spec/TestWorkspace2.xcworkspace/xcuserdata/ray.xcuserdatad/UserInterfaceState.xcuserstate
Binary file not shown.
View
13 spec/builder_spec.rb
@@ -94,6 +94,15 @@
subject.test :sdk => 'macosx10.7'
end
+ it "should not exit when test failed" do
+ Xcode::Shell.stub(:execute)
+ fake_parser = stub(:parser)
+ fake_parser.stub(:failed? => true)
+ fake_parser.stub(:flush)
+ Xcode::Test::Parsers::OCUnitParser.stub(:new => fake_parser)
+ subject.test
+ end
+
end
describe "#clean" do
@@ -110,7 +119,7 @@
end
- it "should clean the project with the default parametesr" do
+ it "should clean the project with the default parameter" do
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
subject.clean
end
@@ -156,7 +165,7 @@
end
- it "should clean the project with the default parametesr" do
+ it "should clean the project with the default parameter" do
Xcode::Shell.should_receive(:execute).with(default_clean_parameters)
subject.clean
end
View
6 spec/ocunit_parser_spec.rb
@@ -75,12 +75,14 @@
it "should detect a passing report" do
t = example_report
- t.failed?.should==false
+ t.should be_succeed
+ t.should_not be_failed
end
it "should detect a failing report" do
t = example_failing_report
- t.failed?.should==true
+ t.should_not be_succeed
+ t.should be_failed
end
it "should record a failure" do
View
11 spec/workspace_spec.rb
@@ -3,9 +3,9 @@
describe Xcode::Workspace do
it "should enumerate all workspaces in current directory" do
workspaces = Xcode.workspaces
- workspaces.size.should==1
- workspaces.first.name.should=="TestWorkspace"
- workspaces.first.projects.size.should==1
+ workspaces.size.should == 2
+ workspaces.first.name.should == "TestWorkspace"
+ workspaces.first.projects.size.should == 1
end
it "should fetch workspace by name" do
@@ -18,6 +18,11 @@
w.should_not be_nil
end
+ it "should handle workspace that use ' in the XML" do
+ w = Xcode.workspace "#{File.dirname(__FILE__)}/TestWorkspace2.xcworkspace"
+ w.should_not be_nil
+ end
+
it "should have many projects" do
w = Xcode.workspace "TestWorkspace"
w.projects.size.should==1

0 comments on commit d1f6e09

Please sign in to comment.
Something went wrong with that request. Please try again.