yarjuf 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rvmrc +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +3 -0
- data/HISTORY.txt +5 -0
- data/README.md +2 -0
- data/Rakefile +23 -0
- data/features/basic.feature +24 -0
- data/features/individual_suites.feature +79 -0
- data/features/individual_tests.feature +73 -0
- data/features/step_definitions/individual_suite_details_steps.rb +24 -0
- data/features/step_definitions/individual_tests_steps.rb +28 -0
- data/features/step_definitions/infrastructure_steps.rb +6 -0
- data/features/step_definitions/suite_level_details_steps.rb +39 -0
- data/features/suite_level_details.feature +77 -0
- data/features/support/env.rb +6 -0
- data/lib/yarjuf.rb +4 -110
- data/lib/yarjuf/j_unit.rb +110 -0
- data/lib/yarjuf/version.rb +3 -0
- data/spec/formatter_conformity_spec.rb +22 -0
- data/spec/spec_helper.rb +2 -0
- data/yarjuf.gemspec +31 -0
- metadata +145 -22
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d8c533296bebf8a3d390108653b7b699c32368db
|
4
|
+
data.tar.gz: b435a6699876a16cc4bdd7e79c3f80165d9005d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ebe9b21ce260c82d1b6db80af520f70d3a2ac5dccd36debc16ca6c7ebcc7e91f8fc9c281d83301660b001e3ca2e026f29cd178724004e57d2dd1fd41aa806d80
|
7
|
+
data.tar.gz: a1170a5987d50163e3ab6e9a64e5ac22eff0bcf0798bf060ebbc4fb91fcfa24213bb695295baeca84fd19ba7c8bac3e7bec00bb76cda3722572fa2739fd02171
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/HISTORY.txt
CHANGED
data/README.md
CHANGED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'cucumber/rake/task'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
namespace :cuke do
|
6
|
+
Cucumber::Rake::Task.new(:all) do |t|
|
7
|
+
t.cucumber_opts = "--format pretty"
|
8
|
+
end
|
9
|
+
|
10
|
+
Cucumber::Rake::Task.new(:wip) do |t|
|
11
|
+
t.cucumber_opts = "--format pretty -t @wip"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :spec do
|
16
|
+
RSpec::Core::RakeTask.new(:all) do |t|
|
17
|
+
t.pattern = "spec/**/*_spec.rb"
|
18
|
+
t.ruby_opts = "-I lib"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => ['spec:all', 'cuke:all']
|
23
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Basic use of Yarjuf
|
2
|
+
As a tester
|
3
|
+
In order to be able to get junit formatted results from rspec
|
4
|
+
I want to be able to use yarjuf
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given a file named "spec/basic_spec.rb" with:
|
8
|
+
"""
|
9
|
+
describe "basic usage" do
|
10
|
+
it "should work" do
|
11
|
+
true.should be_true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: Requiring Yarjuf
|
17
|
+
When I run `rspec spec/basic_spec.rb -r ../../lib/yarjuf -f JUnit`
|
18
|
+
Then the exit status should be 0
|
19
|
+
|
20
|
+
Scenario: Writing output to a file
|
21
|
+
When I run `rspec spec/basic_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
22
|
+
Then the exit status should be 0
|
23
|
+
And a file named "results.xml" should exist
|
24
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
Feature: Individual suites
|
2
|
+
As a tester
|
3
|
+
In order to see relevant tests grouped together in suites
|
4
|
+
I want to be able to differentiate between different `describe` blocks
|
5
|
+
|
6
|
+
Scenario: Differentiating between 2 suites
|
7
|
+
Given a file named "spec/suite_one_spec.rb" with:
|
8
|
+
"""
|
9
|
+
describe "suite one" do
|
10
|
+
it "should contain one test" do
|
11
|
+
1.should == 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
"""
|
15
|
+
And a file named "spec/suite_two_spec.rb" with:
|
16
|
+
"""
|
17
|
+
describe "suite two" do
|
18
|
+
it "should also contain one test" do
|
19
|
+
1.should == 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
"""
|
23
|
+
When I run `rspec spec/suite_one_spec.rb spec/suite_two_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
24
|
+
Then the junit output file contains two testsuite elements named 'suite one' and 'suite two'
|
25
|
+
And the junit output file has one test against each suite
|
26
|
+
|
27
|
+
Scenario: Correct test result counts at individual suite level
|
28
|
+
Given a file named "spec/suite_one_spec.rb" with:
|
29
|
+
"""
|
30
|
+
describe "suite one" do
|
31
|
+
it "should contain one passing test" do
|
32
|
+
1.should == 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should contain one of two failing tests" do
|
36
|
+
1.should == 2
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should contain two of two failing tests" do
|
40
|
+
1.should == 2
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should contain 1 pending test" do
|
44
|
+
pending
|
45
|
+
end
|
46
|
+
end
|
47
|
+
"""
|
48
|
+
And a file named "spec/suite_two_spec.rb" with:
|
49
|
+
"""
|
50
|
+
describe "suite two" do
|
51
|
+
it "should contain one of 3 passing tests" do
|
52
|
+
1.should == 1
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should contain two of 3 passing tests" do
|
56
|
+
1.should == 1
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should contain three of 3 passing tests" do
|
60
|
+
1.should == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should contain one failing test" do
|
64
|
+
1.should == 2
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should contain one of two pending tests" do
|
68
|
+
pending
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should contain two of two pending tests" do
|
72
|
+
pending
|
73
|
+
end
|
74
|
+
end
|
75
|
+
"""
|
76
|
+
When I run `rspec spec/suite_one_spec.rb spec/suite_two_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
77
|
+
Then the junit output file contains two testsuite elements named 'suite one' and 'suite two'
|
78
|
+
And the junit output file has the correct test counts against each suite
|
79
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
Feature: Individual Tests
|
2
|
+
As a tester
|
3
|
+
In order to be able to see details of individual tests
|
4
|
+
I want to write out test results
|
5
|
+
|
6
|
+
Scenario: Simple test name
|
7
|
+
Given a file named "spec/simple_test_name_spec.rb" with:
|
8
|
+
"""
|
9
|
+
describe "suite one" do
|
10
|
+
it "simple name" do
|
11
|
+
1.should == 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
"""
|
15
|
+
When I run `rspec spec/simple_test_name_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
16
|
+
Then the junit output file contains a test result with a simple name
|
17
|
+
|
18
|
+
Scenario: Nested tests
|
19
|
+
Given a file named "spec/nested_spec.rb" with:
|
20
|
+
"""
|
21
|
+
describe "something" do
|
22
|
+
context "that" do
|
23
|
+
context "is" do
|
24
|
+
context "really" do
|
25
|
+
context "deep" do
|
26
|
+
it "should still be displayed nicely" do
|
27
|
+
1.should == 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
"""
|
35
|
+
When I run `rspec spec/nested_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
36
|
+
Then the junit output file has a nicely rendered nested test name
|
37
|
+
|
38
|
+
Scenario: Test duration
|
39
|
+
Given a file named "spec/test_duration_spec.rb" with:
|
40
|
+
"""
|
41
|
+
describe "suite one" do
|
42
|
+
it "should do something" do
|
43
|
+
1.should == 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
"""
|
47
|
+
When I run `rspec spec/test_duration_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
48
|
+
Then the junit output file contains a test with a duration
|
49
|
+
|
50
|
+
Scenario: Pending test
|
51
|
+
Given a file named "spec/pending_test_spec.rb" with:
|
52
|
+
"""
|
53
|
+
describe "suite one" do
|
54
|
+
it "should be pending" do
|
55
|
+
pending
|
56
|
+
end
|
57
|
+
end
|
58
|
+
"""
|
59
|
+
When I run `rspec spec/pending_test_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
60
|
+
Then the junit output file contains a pending test
|
61
|
+
|
62
|
+
Scenario: Failing test
|
63
|
+
Given a file named "spec/failing_test_spec.rb" with:
|
64
|
+
"""
|
65
|
+
describe "suite one" do
|
66
|
+
it "should be failing" do
|
67
|
+
1.should == 2
|
68
|
+
end
|
69
|
+
end
|
70
|
+
"""
|
71
|
+
When I run `rspec spec/failing_test_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
72
|
+
Then the junit output file contains a failing test
|
73
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Then /^the junit output file contains two testsuite elements named 'suite one' and 'suite two'$/ do
|
2
|
+
step 'I parse the junit results file'
|
3
|
+
@results.xpath("/testsuites/testsuite").size.should == 2
|
4
|
+
@results.xpath("/testsuites/testsuite/@name").map(&:text).sort.should == ["suite one", "suite two"]
|
5
|
+
end
|
6
|
+
|
7
|
+
Then /^the junit output file has one test against each suite$/ do
|
8
|
+
step 'I parse the junit results file'
|
9
|
+
@results.xpath("/testsuites/testsuite/@tests").map(&:text).should == ["1", "1"]
|
10
|
+
end
|
11
|
+
|
12
|
+
Then /^the junit output file has the correct test counts against each suite$/ do
|
13
|
+
step 'I parse the junit results file'
|
14
|
+
#suite one
|
15
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite one']/@tests").value.should == "4"
|
16
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite one']/@failures").value.should == "2"
|
17
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite one']/@skipped").value.should == "1"
|
18
|
+
|
19
|
+
#suite two
|
20
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite two']/@tests").value.should == "6"
|
21
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite two']/@failures").value.should == "1"
|
22
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite two']/@skipped").value.should == "2"
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Then /^the junit output file contains a test result with a simple name$/ do
|
2
|
+
step 'I parse the junit results file'
|
3
|
+
@results.at_xpath("/testsuites/testsuite[@name='suite one']/testcase/@name").value.should == "suite one simple name"
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the junit output file has a nicely rendered nested test name$/ do
|
7
|
+
step 'I parse the junit results file'
|
8
|
+
@results.at_xpath("/testsuites/testsuite/testcase/@name").value.should == "something that is really deep should still be displayed nicely"
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^the junit output file contains a test with a duration$/ do
|
12
|
+
step 'I parse the junit results file'
|
13
|
+
@results.at_xpath("/testsuites/testsuite/testcase/@time").value.should match /[.0-9]+/
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^the junit output file contains a pending test$/ do
|
17
|
+
step 'I parse the junit results file'
|
18
|
+
@results.at_xpath("/testsuites/testsuite/testcase/skipped").should_not be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^the junit output file contains a failing test$/ do
|
22
|
+
step 'I parse the junit results file'
|
23
|
+
@results.at_xpath("/testsuites/testsuite/testcase/failure").should_not be_nil
|
24
|
+
@results.at_xpath("/testsuites/testsuite/testcase/failure/@message").value.should == "failed suite one should be failing"
|
25
|
+
@results.at_xpath("/testsuites/testsuite/testcase/failure/@type").value.should == "failed"
|
26
|
+
@results.at_xpath("/testsuites/testsuite/testcase/failure").text.should match /expected.*2.*got.*1.*using.*==.*spec\/failing_test_spec\.rb:3/m
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Then /^the junit output contains the testsuite element$/ do
|
2
|
+
step 'I parse the junit results file'
|
3
|
+
@results.xpath("/testsuites").size.should == 1
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the junit output reports one passing test$/ do
|
7
|
+
step 'I parse the junit results file'
|
8
|
+
@results.at_xpath("/testsuites/@errors").value.should == "0"
|
9
|
+
@results.at_xpath("/testsuites/@failures").value.should == "0"
|
10
|
+
@results.at_xpath("/testsuites/@skipped").value.should == "0"
|
11
|
+
@results.at_xpath("/testsuites/@tests").value.should == "1"
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /^the junit output reports one failing test$/ do
|
15
|
+
step 'I parse the junit results file'
|
16
|
+
@results.at_xpath("/testsuites/@errors").value.should == "0"
|
17
|
+
@results.at_xpath("/testsuites/@failures").value.should == "1"
|
18
|
+
@results.at_xpath("/testsuites/@skipped").value.should == "0"
|
19
|
+
@results.at_xpath("/testsuites/@tests").value.should == "1"
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^the junit output reports one pending test$/ do
|
23
|
+
step 'I parse the junit results file'
|
24
|
+
@results.at_xpath("/testsuites/@errors").value.should == "0"
|
25
|
+
@results.at_xpath("/testsuites/@failures").value.should == "0"
|
26
|
+
@results.at_xpath("/testsuites/@skipped").value.should == "1"
|
27
|
+
@results.at_xpath("/testsuites/@tests").value.should == "1"
|
28
|
+
end
|
29
|
+
|
30
|
+
Then /^the junit output testsuite element contains a duration$/ do
|
31
|
+
step 'I parse the junit results file'
|
32
|
+
@results.at_xpath("/testsuites/@time").value.should match /[.0-9]+/
|
33
|
+
end
|
34
|
+
|
35
|
+
Then /^the junit output testsuite element contains a timestamp$/ do
|
36
|
+
step 'I parse the junit results file'
|
37
|
+
@results.at_xpath("/testsuites/@timestamp").value.should match /\d{4}-\d{2}-\d{2}T\d+:\d+:\d+\+\d+:\d+/
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
Feature: Suite Summary
|
2
|
+
As a tester
|
3
|
+
In order to make the summary detail visible in jenkins
|
4
|
+
I want to output the suite summary level detail to the output
|
5
|
+
|
6
|
+
Scenario: testsuites element present
|
7
|
+
Given a file named "spec/suite_element_spec.rb" with:
|
8
|
+
"""
|
9
|
+
describe "suite element" do
|
10
|
+
it "should be present" do
|
11
|
+
1.should == 1
|
12
|
+
end
|
13
|
+
end
|
14
|
+
"""
|
15
|
+
When I run `rspec spec/suite_element_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
16
|
+
Then the junit output contains the testsuite element
|
17
|
+
|
18
|
+
Scenario: One passing test
|
19
|
+
Given a file named "spec/one_passing_test_spec.rb" with:
|
20
|
+
"""
|
21
|
+
describe "suite level details for 1 passing test" do
|
22
|
+
it "should pass" do
|
23
|
+
1.should == 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
"""
|
27
|
+
When I run `rspec spec/one_passing_test_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
28
|
+
Then the junit output reports one passing test
|
29
|
+
|
30
|
+
Scenario: One failing test
|
31
|
+
Given a file named "spec/one_failing_test_spec.rb" with:
|
32
|
+
"""
|
33
|
+
describe "suite level details for 1 failing test" do
|
34
|
+
it "should fail" do
|
35
|
+
1.should == 2
|
36
|
+
end
|
37
|
+
end
|
38
|
+
"""
|
39
|
+
When I run `rspec spec/one_failing_test_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
40
|
+
Then the junit output reports one failing test
|
41
|
+
|
42
|
+
Scenario: One pending test
|
43
|
+
Given a file named "spec/one_pending_test_spec.rb" with:
|
44
|
+
"""
|
45
|
+
describe "suite level details for 1 pending test" do
|
46
|
+
it "should be pending" do
|
47
|
+
pending
|
48
|
+
end
|
49
|
+
end
|
50
|
+
"""
|
51
|
+
When I run `rspec spec/one_pending_test_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
52
|
+
Then the junit output reports one pending test
|
53
|
+
|
54
|
+
Scenario: Test suite duration
|
55
|
+
Given a file named "spec/suite_duration_spec.rb" with:
|
56
|
+
"""
|
57
|
+
describe "suite element duration" do
|
58
|
+
it "should contain a duration" do
|
59
|
+
1.should == 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
"""
|
63
|
+
When I run `rspec spec/suite_duration_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
64
|
+
Then the junit output testsuite element contains a duration
|
65
|
+
|
66
|
+
Scenario: Test suite time stamp
|
67
|
+
Given a file named "spec/suite_timestamp_spec.rb" with:
|
68
|
+
"""
|
69
|
+
describe "suite element timestamp" do
|
70
|
+
it "should contain a timestamp" do
|
71
|
+
1.should == 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
"""
|
75
|
+
When I run `rspec spec/suite_timestamp_spec.rb -r ../../lib/yarjuf -f JUnit -o results.xml`
|
76
|
+
Then the junit output testsuite element contains a timestamp
|
77
|
+
|
data/lib/yarjuf.rb
CHANGED
@@ -1,114 +1,8 @@
|
|
1
|
+
# external dependencies
|
1
2
|
require 'time'
|
2
3
|
require 'builder'
|
3
4
|
require 'rspec/core/formatters/base_formatter'
|
4
5
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
#rspec formatter methods we care about
|
9
|
-
|
10
|
-
def initialize(output)
|
11
|
-
super output
|
12
|
-
@test_suite_results = {}
|
13
|
-
@builder = Builder::XmlMarkup.new :indent => 2
|
14
|
-
end
|
15
|
-
|
16
|
-
def example_passed(example)
|
17
|
-
add_to_test_suite_results example
|
18
|
-
end
|
19
|
-
|
20
|
-
def example_failed(example)
|
21
|
-
add_to_test_suite_results example
|
22
|
-
end
|
23
|
-
|
24
|
-
def example_pending(example)
|
25
|
-
add_to_test_suite_results example
|
26
|
-
end
|
27
|
-
|
28
|
-
def dump_summary(duration, example_count, failure_count, pending_count)
|
29
|
-
build_results duration, example_count, failure_count, pending_count
|
30
|
-
output.puts @builder.target!
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
def add_to_test_suite_results(example)
|
36
|
-
suite_name = JUnit.root_group_name_for example
|
37
|
-
@test_suite_results[suite_name] = [] unless @test_suite_results.keys.include? suite_name
|
38
|
-
@test_suite_results[suite_name] << example
|
39
|
-
end
|
40
|
-
|
41
|
-
def failure_details_for(example)
|
42
|
-
exception = example.metadata[:execution_result][:exception]
|
43
|
-
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace, example).join("\n")}"
|
44
|
-
end
|
45
|
-
|
46
|
-
#utility methods
|
47
|
-
|
48
|
-
def self.count_in_suite_of_type(suite, test_case_result_type)
|
49
|
-
suite.select {|example| example.metadata[:execution_result][:status] == test_case_result_type}.size
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.root_group_name_for(example)
|
53
|
-
group_hierarchy = []
|
54
|
-
current_example_group = example.metadata[:example_group]
|
55
|
-
until current_example_group.nil? do
|
56
|
-
group_hierarchy.unshift current_example_group
|
57
|
-
current_example_group = current_example_group[:example_group]
|
58
|
-
end
|
59
|
-
group_hierarchy.first[:description]
|
60
|
-
end
|
61
|
-
|
62
|
-
#methods to build the xml for test suites and individual tests
|
63
|
-
|
64
|
-
def build_results(duration, example_count, failure_count, pending_count)
|
65
|
-
@builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
66
|
-
@builder.testsuites :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
67
|
-
build_all_suites
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def build_all_suites
|
72
|
-
@test_suite_results.each do |suite_name, tests|
|
73
|
-
build_test_suite suite_name, tests
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def build_test_suite(suite_name, tests)
|
78
|
-
failure_count = JUnit.count_in_suite_of_type tests, "failed"
|
79
|
-
skipped_count = JUnit.count_in_suite_of_type tests, "pending"
|
80
|
-
|
81
|
-
@builder.testsuite :name => suite_name, :tests => tests.size, :errors => 0, :failures => failure_count, :skipped => skipped_count do
|
82
|
-
@builder.properties
|
83
|
-
build_all_tests tests
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def build_all_tests(tests)
|
88
|
-
tests.each do |test|
|
89
|
-
build_test test
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def build_test(test)
|
94
|
-
test_name = test.metadata[:full_description]
|
95
|
-
execution_time = test.metadata[:execution_result][:run_time]
|
96
|
-
test_status = test.metadata[:execution_result][:status]
|
97
|
-
|
98
|
-
@builder.testcase :name => test_name, :time => execution_time do
|
99
|
-
case test_status
|
100
|
-
when "pending" then @builder.skipped
|
101
|
-
when "failed" then build_failed_test test
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def build_failed_test(test)
|
107
|
-
failure_message = "failed #{test.metadata[:full_description]}"
|
108
|
-
|
109
|
-
@builder.failure :message => failure_message, :type => "failed" do
|
110
|
-
@builder.cdata! failure_details_for test
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
6
|
+
# internal dependencies
|
7
|
+
require 'yarjuf/j_unit'
|
8
|
+
require 'yarjuf/version'
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#An RSpec formatter for generating results in JUnit format
|
2
|
+
class JUnit < RSpec::Core::Formatters::BaseFormatter
|
3
|
+
|
4
|
+
#rspec formatter methods we care about
|
5
|
+
|
6
|
+
def initialize(output)
|
7
|
+
super output
|
8
|
+
@test_suite_results = {}
|
9
|
+
@builder = Builder::XmlMarkup.new :indent => 2
|
10
|
+
end
|
11
|
+
|
12
|
+
def example_passed(example)
|
13
|
+
add_to_test_suite_results example
|
14
|
+
end
|
15
|
+
|
16
|
+
def example_failed(example)
|
17
|
+
add_to_test_suite_results example
|
18
|
+
end
|
19
|
+
|
20
|
+
def example_pending(example)
|
21
|
+
add_to_test_suite_results example
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
25
|
+
build_results duration, example_count, failure_count, pending_count
|
26
|
+
output.puts @builder.target!
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def add_to_test_suite_results(example)
|
32
|
+
suite_name = JUnit.root_group_name_for example
|
33
|
+
@test_suite_results[suite_name] = [] unless @test_suite_results.keys.include? suite_name
|
34
|
+
@test_suite_results[suite_name] << example
|
35
|
+
end
|
36
|
+
|
37
|
+
def failure_details_for(example)
|
38
|
+
exception = example.metadata[:execution_result][:exception]
|
39
|
+
exception.nil? ? "" : "#{exception.message}\n#{format_backtrace(exception.backtrace, example).join("\n")}"
|
40
|
+
end
|
41
|
+
|
42
|
+
#utility methods
|
43
|
+
|
44
|
+
def self.count_in_suite_of_type(suite, test_case_result_type)
|
45
|
+
suite.select {|example| example.metadata[:execution_result][:status] == test_case_result_type}.size
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.root_group_name_for(example)
|
49
|
+
group_hierarchy = []
|
50
|
+
current_example_group = example.metadata[:example_group]
|
51
|
+
until current_example_group.nil? do
|
52
|
+
group_hierarchy.unshift current_example_group
|
53
|
+
current_example_group = current_example_group[:example_group]
|
54
|
+
end
|
55
|
+
group_hierarchy.first[:description]
|
56
|
+
end
|
57
|
+
|
58
|
+
#methods to build the xml for test suites and individual tests
|
59
|
+
|
60
|
+
def build_results(duration, example_count, failure_count, pending_count)
|
61
|
+
@builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
62
|
+
@builder.testsuites :errors => 0, :failures => failure_count, :skipped => pending_count, :tests => example_count, :time => duration, :timestamp => Time.now.iso8601 do
|
63
|
+
build_all_suites
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_all_suites
|
68
|
+
@test_suite_results.each do |suite_name, tests|
|
69
|
+
build_test_suite suite_name, tests
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_test_suite(suite_name, tests)
|
74
|
+
failure_count = JUnit.count_in_suite_of_type tests, "failed"
|
75
|
+
skipped_count = JUnit.count_in_suite_of_type tests, "pending"
|
76
|
+
|
77
|
+
@builder.testsuite :name => suite_name, :tests => tests.size, :errors => 0, :failures => failure_count, :skipped => skipped_count do
|
78
|
+
@builder.properties
|
79
|
+
build_all_tests tests
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def build_all_tests(tests)
|
84
|
+
tests.each do |test|
|
85
|
+
build_test test
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_test(test)
|
90
|
+
test_name = test.metadata[:full_description]
|
91
|
+
execution_time = test.metadata[:execution_result][:run_time]
|
92
|
+
test_status = test.metadata[:execution_result][:status]
|
93
|
+
|
94
|
+
@builder.testcase :name => test_name, :time => execution_time do
|
95
|
+
case test_status
|
96
|
+
when "pending" then @builder.skipped
|
97
|
+
when "failed" then build_failed_test test
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_failed_test(test)
|
103
|
+
failure_message = "failed #{test.metadata[:full_description]}"
|
104
|
+
|
105
|
+
@builder.failure :message => failure_message, :type => "failed" do
|
106
|
+
@builder.cdata! failure_details_for test
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
describe JUnit do
|
2
|
+
context "interface conformity" do
|
3
|
+
subject { JUnit.new "some output" }
|
4
|
+
|
5
|
+
it "should respond to example passed" do
|
6
|
+
should respond_to :example_passed
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should respond to example failed" do
|
10
|
+
should respond_to :example_failed
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should respond to example pending" do
|
14
|
+
should respond_to :example_pending
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should respond to dump summary" do
|
18
|
+
should respond_to :dump_summary
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/spec/spec_helper.rb
ADDED
data/yarjuf.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'yarjuf/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'yarjuf'
|
8
|
+
gem.version = Yarjuf::VERSION
|
9
|
+
gem.platform = Gem::Platform::RUBY
|
10
|
+
gem.authors = ['Nat Ritmeyer']
|
11
|
+
gem.email = ['nat@natontesting.com']
|
12
|
+
gem.homepage = 'http://github.com/natritmeyer/yarjuf'
|
13
|
+
gem.summary = 'Yet Another RSpec JUnit Formatter (for Hudson/Jenkins)'
|
14
|
+
gem.description = 'Yet Another RSpec JUnit Formatter (for Hudson/Jenkins)'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ['lib']
|
20
|
+
|
21
|
+
gem.add_runtime_dependency('rspec', '~> 2.12')
|
22
|
+
gem.add_runtime_dependency('builder')
|
23
|
+
|
24
|
+
gem.add_development_dependency('nokogiri', '~> 1.5.10') # for Ruby 1.8.7
|
25
|
+
gem.add_development_dependency('rake')
|
26
|
+
gem.add_development_dependency('cucumber')
|
27
|
+
gem.add_development_dependency('aruba')
|
28
|
+
gem.add_development_dependency('simplecov')
|
29
|
+
gem.add_development_dependency('reek', ['= 1.3.7']) # for Ruby 1.8.7
|
30
|
+
gem.add_development_dependency('rainbow', '~> 1.99.2') # for Ruby 1.8.7
|
31
|
+
end
|
metadata
CHANGED
@@ -1,48 +1,141 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yarjuf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.6
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Nat Ritmeyer
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-07-28 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '2.
|
19
|
+
version: '2.12'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '2.
|
26
|
+
version: '2.12'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: builder
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.5.10
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.5.10
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: cucumber
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: aruba
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: reek
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.3.7
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.3.7
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rainbow
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.99.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.99.2
|
46
139
|
description: Yet Another RSpec JUnit Formatter (for Hudson/Jenkins)
|
47
140
|
email:
|
48
141
|
- nat@natontesting.com
|
@@ -50,32 +143,62 @@ executables: []
|
|
50
143
|
extensions: []
|
51
144
|
extra_rdoc_files: []
|
52
145
|
files:
|
53
|
-
-
|
54
|
-
-
|
146
|
+
- ".gitignore"
|
147
|
+
- ".rspec"
|
148
|
+
- ".rvmrc"
|
149
|
+
- ".travis.yml"
|
150
|
+
- Gemfile
|
55
151
|
- HISTORY.txt
|
152
|
+
- LICENSE.txt
|
56
153
|
- README.md
|
154
|
+
- Rakefile
|
155
|
+
- features/basic.feature
|
156
|
+
- features/individual_suites.feature
|
157
|
+
- features/individual_tests.feature
|
158
|
+
- features/step_definitions/individual_suite_details_steps.rb
|
159
|
+
- features/step_definitions/individual_tests_steps.rb
|
160
|
+
- features/step_definitions/infrastructure_steps.rb
|
161
|
+
- features/step_definitions/suite_level_details_steps.rb
|
162
|
+
- features/suite_level_details.feature
|
163
|
+
- features/support/env.rb
|
164
|
+
- lib/yarjuf.rb
|
165
|
+
- lib/yarjuf/j_unit.rb
|
166
|
+
- lib/yarjuf/version.rb
|
167
|
+
- spec/formatter_conformity_spec.rb
|
168
|
+
- spec/spec_helper.rb
|
169
|
+
- yarjuf.gemspec
|
57
170
|
homepage: http://github.com/natritmeyer/yarjuf
|
58
171
|
licenses: []
|
172
|
+
metadata: {}
|
59
173
|
post_install_message:
|
60
174
|
rdoc_options: []
|
61
175
|
require_paths:
|
62
176
|
- lib
|
63
177
|
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
-
none: false
|
65
178
|
requirements:
|
66
|
-
- -
|
179
|
+
- - ">="
|
67
180
|
- !ruby/object:Gem::Version
|
68
181
|
version: '0'
|
69
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
-
none: false
|
71
183
|
requirements:
|
72
|
-
- -
|
184
|
+
- - ">="
|
73
185
|
- !ruby/object:Gem::Version
|
74
186
|
version: '0'
|
75
187
|
requirements: []
|
76
188
|
rubyforge_project:
|
77
|
-
rubygems_version:
|
189
|
+
rubygems_version: 2.2.2
|
78
190
|
signing_key:
|
79
|
-
specification_version:
|
191
|
+
specification_version: 4
|
80
192
|
summary: Yet Another RSpec JUnit Formatter (for Hudson/Jenkins)
|
81
|
-
test_files:
|
193
|
+
test_files:
|
194
|
+
- features/basic.feature
|
195
|
+
- features/individual_suites.feature
|
196
|
+
- features/individual_tests.feature
|
197
|
+
- features/step_definitions/individual_suite_details_steps.rb
|
198
|
+
- features/step_definitions/individual_tests_steps.rb
|
199
|
+
- features/step_definitions/infrastructure_steps.rb
|
200
|
+
- features/step_definitions/suite_level_details_steps.rb
|
201
|
+
- features/suite_level_details.feature
|
202
|
+
- features/support/env.rb
|
203
|
+
- spec/formatter_conformity_spec.rb
|
204
|
+
- spec/spec_helper.rb
|