jenkins_junit_builder 0.0.1
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 +14 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/Rakefile +8 -0
- data/jenkins_junit.xsd +104 -0
- data/jenkins_junit_builder.gemspec +23 -0
- data/lib/jenkins_junit_builder/case.rb +59 -0
- data/lib/jenkins_junit_builder/file_not_found_exception.rb +4 -0
- data/lib/jenkins_junit_builder/suite.rb +105 -0
- data/lib/jenkins_junit_builder/system_message.rb +26 -0
- data/lib/jenkins_junit_builder/version.rb +3 -0
- data/lib/jenkins_junit_builder.rb +5 -0
- data/sample_report.xml +59 -0
- data/test/minitest_helper.rb +14 -0
- data/test/test_jenkins_junit_builder.rb +187 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 33822e56ec15194ce281061c468d7a5cf8374cdb
|
4
|
+
data.tar.gz: e68499a7cfbd1c9e66b41f1380fcd04fd52efe6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 80dcfbe99a716225fa2bb2c586d449d29b4d9512f71ff9c0839db3e8f4caf8d52066ceb3ce965b8ea39f9717ab8bd4b78c21a785de1fa24c5aeac0095be99e17
|
7
|
+
data.tar.gz: 3787d259b5be5766ed0550753dd54fbeb5680898883925a9a1231bd3179a44a4b0252c9d2e279d14e70ad0ea695e4d954cb2dd009bf0ebe535224bad9d078bfe
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Viktor Vad [vad.viktor@gmail.com]
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Jenkins CI compatible Junit XML report builder
|
2
|
+
|
3
|
+
When you have your own home brewed testing framework but still want to use [Jenkins CI](http://jenkins-ci.org/) with it's standard [JUnit plugin](https://wiki.jenkins-ci.org/display/JENKINS/JUnit+Plugin), you may find yourself searching for a valid and recent documentation on how to create such XML documents. It's hard. Harder for newbies who want to learn how to set up/use Jenkins and make it useful to their projects.
|
4
|
+
|
5
|
+
The XSD schema that serves as a base of the XMLs generated can be found [here](https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-7.xsd).
|
6
|
+
|
7
|
+
I have put together a [blog entry](http://ikonote.blogspot.ie/2015/03/how-to-create-jenins-ci-compatible.html) on describing how the XML is interpreted and presented by Jenkins.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'jenkins_junit_builder'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install jenkins_junit_builder
|
24
|
+
|
25
|
+
Since it uses [Nokogiri](http://www.nokogiri.org/) to build report XMLs, please refer to [Nokogiri's documentation](http://www.nokogiri.org/tutorials/installing_nokogiri.html) for more installation instructions if you run into build errors.
|
26
|
+
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Please note that understanding how to [read an XSD schema](http://www.w3.org/TR/xmlschema11-1/) (which is [not that hard](http://www.w3schools.com/schema/default.asp)) will really help navigating and understanding what properties are available and how to structure them.
|
31
|
+
Again, Jenkins looks like to work by this [XSD schema](https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-7.xsd).
|
32
|
+
|
33
|
+
Since we are building our own testing system, I did something that is not soooo magical as a DSL with raibows and [Unikitties](http://lego.wikia.com/wiki/Unikitty).
|
34
|
+
|
35
|
+
----------
|
36
|
+
|
37
|
+
Let's report a pass:
|
38
|
+
```ruby
|
39
|
+
t_passed = JenkinsJunitBuilder::Case.new
|
40
|
+
t_passed.name = 'My first test case'
|
41
|
+
t_passed.time = 65
|
42
|
+
t_passed.classname = 'FirstTestSuite'
|
43
|
+
t_passed.result = JenkinsJunitBuilder::Case::RESULT_PASSED
|
44
|
+
```
|
45
|
+
|
46
|
+
Then a failure:
|
47
|
+
```ruby
|
48
|
+
t_failed = JenkinsJunitBuilder::Case.new
|
49
|
+
t_failed.name = 'My failing functionality'
|
50
|
+
t_failed.classname = 'FirstTestSuite'
|
51
|
+
t_failed.result = JenkinsJunitBuilder::Case::RESULT_FAILURE
|
52
|
+
t_failed.message = 'timeout reached'
|
53
|
+
t_failed.system_out.message = 'some thing went wrong'
|
54
|
+
t_failed.system_err.message = 'give me a stacktrace or something'
|
55
|
+
```
|
56
|
+
|
57
|
+
Add those to the suite:
|
58
|
+
```ruby
|
59
|
+
t_suite = JenkinsJunitBuilder::Suite.new
|
60
|
+
t_suite.name = 'Testing some cases'
|
61
|
+
t_suite.add_case t_passed
|
62
|
+
t_suite.add_case t_failed
|
63
|
+
```
|
64
|
+
|
65
|
+
And bake them:
|
66
|
+
```ruby
|
67
|
+
xml_report = t_suite.build_report
|
68
|
+
```
|
69
|
+
|
70
|
+
Into this:
|
71
|
+
```xml
|
72
|
+
<testsuites>
|
73
|
+
<testsuite name="Testing some cases">
|
74
|
+
<testcase name="My first test case" time="65" classname="FirstTestSuite"/>
|
75
|
+
<testcase name="My failing functionality" classname="FirstTestSuite">
|
76
|
+
<failure message="timeout reached"/>
|
77
|
+
<system-out>some thing went wrong</system-out>
|
78
|
+
<system-err>give me a stacktrace or something</system-err>
|
79
|
+
</testcase>
|
80
|
+
</testsuite>
|
81
|
+
</testsuites>
|
82
|
+
```
|
83
|
+
|
84
|
+
Please refer to the tests and code for more guidance for the time being.
|
85
|
+
|
86
|
+
----------
|
87
|
+
|
88
|
+
|
89
|
+
## Contributing
|
90
|
+
|
91
|
+
1. Fork it ( https://github.com/vadviktor/jenkins_junit_builder/fork )
|
92
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
93
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
94
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
95
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/jenkins_junit.xsd
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
3
|
+
|
4
|
+
<xs:element name="failure">
|
5
|
+
<xs:complexType mixed="true">
|
6
|
+
<xs:attribute name="type" type="xs:string" use="optional"/>
|
7
|
+
<xs:attribute name="message" type="xs:string" use="optional"/>
|
8
|
+
</xs:complexType>
|
9
|
+
</xs:element>
|
10
|
+
|
11
|
+
<xs:element name="error">
|
12
|
+
<xs:complexType mixed="true">
|
13
|
+
<xs:attribute name="type" type="xs:string" use="optional"/>
|
14
|
+
<xs:attribute name="message" type="xs:string" use="optional"/>
|
15
|
+
</xs:complexType>
|
16
|
+
</xs:element>
|
17
|
+
|
18
|
+
<xs:element name="skipped">
|
19
|
+
<xs:complexType mixed="true">
|
20
|
+
<xs:attribute name="type" type="xs:string" use="optional"/>
|
21
|
+
<xs:attribute name="message" type="xs:string" use="optional"/>
|
22
|
+
</xs:complexType>
|
23
|
+
</xs:element>
|
24
|
+
|
25
|
+
<xs:element name="properties">
|
26
|
+
<xs:complexType>
|
27
|
+
<xs:sequence>
|
28
|
+
<xs:element ref="property" minOccurs="0" maxOccurs="unbounded"/>
|
29
|
+
</xs:sequence>
|
30
|
+
</xs:complexType>
|
31
|
+
</xs:element>
|
32
|
+
|
33
|
+
<xs:element name="property">
|
34
|
+
<xs:complexType>
|
35
|
+
<xs:attribute name="name" type="xs:string" use="required"/>
|
36
|
+
<xs:attribute name="value" type="xs:string" use="required"/>
|
37
|
+
</xs:complexType>
|
38
|
+
</xs:element>
|
39
|
+
|
40
|
+
<xs:element name="system-err" type="xs:string"/>
|
41
|
+
<xs:element name="system-out" type="xs:string"/>
|
42
|
+
|
43
|
+
<xs:element name="testcase">
|
44
|
+
<xs:complexType>
|
45
|
+
<xs:sequence>
|
46
|
+
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
47
|
+
<xs:element ref="skipped"/>
|
48
|
+
<xs:element ref="error"/>
|
49
|
+
<xs:element ref="failure"/>
|
50
|
+
<xs:element ref="system-out"/>
|
51
|
+
<xs:element ref="system-err"/>
|
52
|
+
</xs:choice>
|
53
|
+
</xs:sequence>
|
54
|
+
<xs:attribute name="name" type="xs:string" use="required"/>
|
55
|
+
<xs:attribute name="assertions" type="xs:string" use="optional"/>
|
56
|
+
<xs:attribute name="time" type="xs:string" use="optional"/>
|
57
|
+
<xs:attribute name="classname" type="xs:string" use="optional"/>
|
58
|
+
<xs:attribute name="status" type="xs:string" use="optional"/>
|
59
|
+
<xs:attribute name="class" type="xs:string" use="optional"/>
|
60
|
+
<xs:attribute name="file" type="xs:string" use="optional"/>
|
61
|
+
<xs:attribute name="line" type="xs:string" use="optional"/>
|
62
|
+
</xs:complexType>
|
63
|
+
</xs:element>
|
64
|
+
|
65
|
+
<xs:element name="testsuite">
|
66
|
+
<xs:complexType>
|
67
|
+
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
68
|
+
<xs:element ref="testsuite"/>
|
69
|
+
<xs:element ref="properties"/>
|
70
|
+
<xs:element ref="testcase"/>
|
71
|
+
<xs:element ref="system-out"/>
|
72
|
+
<xs:element ref="system-err"/>
|
73
|
+
</xs:choice>
|
74
|
+
<xs:attribute name="name" type="xs:string" use="optional"/>
|
75
|
+
<xs:attribute name="tests" type="xs:string" use="required"/>
|
76
|
+
<xs:attribute name="failures" type="xs:string" use="optional"/>
|
77
|
+
<xs:attribute name="errors" type="xs:string" use="optional"/>
|
78
|
+
<xs:attribute name="time" type="xs:string" use="optional"/>
|
79
|
+
<xs:attribute name="disabled" type="xs:string" use="optional"/>
|
80
|
+
<xs:attribute name="skipped" type="xs:string" use="optional"/>
|
81
|
+
<xs:attribute name="timestamp" type="xs:string" use="optional"/>
|
82
|
+
<xs:attribute name="hostname" type="xs:string" use="optional"/>
|
83
|
+
<xs:attribute name="id" type="xs:string" use="optional"/>
|
84
|
+
<xs:attribute name="package" type="xs:string" use="optional"/>
|
85
|
+
<xs:attribute name="assertions" type="xs:string" use="optional"/>
|
86
|
+
<xs:attribute name="file" type="xs:string" use="optional"/>
|
87
|
+
</xs:complexType>
|
88
|
+
</xs:element>
|
89
|
+
|
90
|
+
<xs:element name="testsuites">
|
91
|
+
<xs:complexType>
|
92
|
+
<xs:sequence>
|
93
|
+
<xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/>
|
94
|
+
</xs:sequence>
|
95
|
+
<xs:attribute name="name" type="xs:string" use="optional"/>
|
96
|
+
<xs:attribute name="time" type="xs:string" use="optional"/>
|
97
|
+
<xs:attribute name="tests" type="xs:string" use="optional"/>
|
98
|
+
<xs:attribute name="failures" type="xs:string" use="optional"/>
|
99
|
+
<xs:attribute name="disabled" type="xs:string" use="optional"/>
|
100
|
+
<xs:attribute name="errors" type="xs:string" use="optional"/>
|
101
|
+
</xs:complexType>
|
102
|
+
</xs:element>
|
103
|
+
|
104
|
+
</xs:schema>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'pathname'
|
3
|
+
require Pathname.new(__dir__) + 'lib/jenkins_junit_builder/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'jenkins_junit_builder'
|
7
|
+
spec.version = JenkinsJunitBuilder::VERSION
|
8
|
+
spec.authors = ['Viktor Vad']
|
9
|
+
spec.email = ['vad.viktor@gmail.com']
|
10
|
+
spec.summary = %q{Build test reports in Jenkins CI JUnit XML format.}
|
11
|
+
spec.description = %q{A factory that helps you build Jenkins CI compatible JUnit XML reports for your tests.}
|
12
|
+
spec.homepage = 'https://github.com/vadviktor/jenkins_junit_builder'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
21
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
22
|
+
spec.add_development_dependency 'minitest'
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname.new(__dir__) + 'system_message'
|
3
|
+
|
4
|
+
module JenkinsJunitBuilder
|
5
|
+
class Case
|
6
|
+
attr_accessor :name, :time, :classname
|
7
|
+
attr_reader :result, :message
|
8
|
+
|
9
|
+
RESULT_PASSED = :passed
|
10
|
+
RESULT_SKIPPED = :skipped
|
11
|
+
RESULT_FAILURE = :failure
|
12
|
+
RESULT_ERROR = :error
|
13
|
+
|
14
|
+
# Should we report any message for this result type?
|
15
|
+
def result_has_message?
|
16
|
+
[RESULT_FAILURE, RESULT_ERROR, RESULT_SKIPPED].include? result
|
17
|
+
end
|
18
|
+
|
19
|
+
def system_out
|
20
|
+
@system_out ||= SystemMessage.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def system_err
|
24
|
+
@system_err ||= SystemMessage.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [Symbol] type [:passed, :skipped, :failure, :error]
|
28
|
+
def result=(type)
|
29
|
+
throw ArgumentError.new "'#{type.to_s}' is not a valid case result type" unless [:passed, :skipped, :failure, :error].include? type
|
30
|
+
|
31
|
+
@result = type
|
32
|
+
end
|
33
|
+
|
34
|
+
def passed
|
35
|
+
self.result = RESULT_PASSED
|
36
|
+
end
|
37
|
+
|
38
|
+
def skipped
|
39
|
+
self.result = RESULT_SKIPPED
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure
|
43
|
+
self.result = RESULT_FAILURE
|
44
|
+
end
|
45
|
+
|
46
|
+
def error
|
47
|
+
self.result = RESULT_ERROR
|
48
|
+
end
|
49
|
+
|
50
|
+
# Short message provided by the result type element.
|
51
|
+
# Not used in non-failing tests.
|
52
|
+
#
|
53
|
+
# @param [String] msg
|
54
|
+
def message=(msg)
|
55
|
+
@message = msg
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'pathname'
|
4
|
+
require Pathname.new(__dir__) + 'file_not_found_exception'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
module JenkinsJunitBuilder
|
8
|
+
class Suite
|
9
|
+
|
10
|
+
attr_accessor :name, :report_path, :append_report
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@cases = []
|
14
|
+
self.append_report = true
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
def add_case(test_case)
|
19
|
+
@cases << test_case
|
20
|
+
end
|
21
|
+
|
22
|
+
# In short, this is the XML string that makes the report.
|
23
|
+
#
|
24
|
+
# @return [String] XML report
|
25
|
+
def build_report
|
26
|
+
# build cases
|
27
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
28
|
+
xml.testsuites {
|
29
|
+
testsuite = xml.testsuite {
|
30
|
+
@cases.each do |tc|
|
31
|
+
testcase = xml.testcase {
|
32
|
+
if tc.result_has_message?
|
33
|
+
result_type = xml.send(tc.result)
|
34
|
+
result_type[:message] = tc.message if tc.message.present?
|
35
|
+
end
|
36
|
+
|
37
|
+
if tc.system_out.size > 0
|
38
|
+
xml.send('system-out') { xml.text tc.system_out.to_s }
|
39
|
+
end
|
40
|
+
|
41
|
+
if tc.system_err.size > 0
|
42
|
+
xml.send('system-err') { xml.text tc.system_err.to_s }
|
43
|
+
end
|
44
|
+
}
|
45
|
+
|
46
|
+
testcase[:name] = tc.name if tc.name.present?
|
47
|
+
testcase[:time] = tc.time if tc.time.present?
|
48
|
+
testcase[:classname] = tc.classname if tc.classname.present?
|
49
|
+
end
|
50
|
+
}
|
51
|
+
|
52
|
+
testsuite[:name] = name if name.present?
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
builder.parent.root.to_xml
|
57
|
+
end
|
58
|
+
|
59
|
+
# Writes the report to the specified file
|
60
|
+
# also returns the new XML report content
|
61
|
+
#
|
62
|
+
# @return [String] final XML report content
|
63
|
+
def write_report_file
|
64
|
+
raise FileNotFoundException.new 'There is no report file path specified' if report_path.blank?
|
65
|
+
|
66
|
+
report = build_report
|
67
|
+
|
68
|
+
if append_report.present? && File.exist?(report_path)
|
69
|
+
f = File.open(report_path)
|
70
|
+
existing_xml = Nokogiri::XML(f)
|
71
|
+
f.close
|
72
|
+
|
73
|
+
report = existing_xml.root << Nokogiri::XML(report).at('testsuite')
|
74
|
+
|
75
|
+
# formatting
|
76
|
+
report = format_xml report.to_xml
|
77
|
+
end
|
78
|
+
|
79
|
+
File.write report_path, report
|
80
|
+
report
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
# @params [String] XML string
|
86
|
+
def format_xml(xml_text)
|
87
|
+
xsl =<<XSL
|
88
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
89
|
+
<xsl:output method="xml" encoding="utf-8"/>
|
90
|
+
<xsl:strip-space elements="*"/>
|
91
|
+
<xsl:template match="/">
|
92
|
+
<xsl:copy-of select="."/>
|
93
|
+
</xsl:template>
|
94
|
+
</xsl:stylesheet>
|
95
|
+
XSL
|
96
|
+
|
97
|
+
doc = Nokogiri::XML(xml_text)
|
98
|
+
xslt = Nokogiri::XSLT(xsl)
|
99
|
+
out = xslt.transform(doc)
|
100
|
+
|
101
|
+
out.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::DEFAULT_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION).strip
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module JenkinsJunitBuilder
|
2
|
+
class SystemMessage
|
3
|
+
|
4
|
+
def initialize(msg = nil)
|
5
|
+
@message = []
|
6
|
+
self.message = msg unless msg.nil?
|
7
|
+
end
|
8
|
+
|
9
|
+
def size
|
10
|
+
@message.size
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
@message.join "\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
def message=(msg)
|
18
|
+
@message = [msg]
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(msg)
|
22
|
+
@message << msg
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/sample_report.xml
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<testsuites>
|
3
|
+
|
4
|
+
<testsuite name="test.host.ie">
|
5
|
+
<testcase name="001-req-03" time="20" classname="Arbour">
|
6
|
+
</testcase>
|
7
|
+
|
8
|
+
<testcase name="002-req-04" time="30" classname="Arbour">
|
9
|
+
<skipped message="not implemented yet"/>
|
10
|
+
</testcase>
|
11
|
+
|
12
|
+
<testcase name="003-req-13" time="50" classname="Arbour">
|
13
|
+
<failure message="timeout reached"/>
|
14
|
+
<system-out>
|
15
|
+
this is the
|
16
|
+
STDOUT
|
17
|
+
from the
|
18
|
+
system itself
|
19
|
+
</system-out>
|
20
|
+
</testcase>
|
21
|
+
|
22
|
+
<testcase name="004-req-14" time="10" classname="Arbour">
|
23
|
+
<error message="'rot' is not a valid parameter"/>
|
24
|
+
<system-out>
|
25
|
+
this is the
|
26
|
+
STDOUT
|
27
|
+
from the
|
28
|
+
system itself
|
29
|
+
</system-out>
|
30
|
+
<system-err>
|
31
|
+
this is the
|
32
|
+
STDERR
|
33
|
+
from the
|
34
|
+
system itself
|
35
|
+
</system-err>
|
36
|
+
</testcase>
|
37
|
+
</testsuite>
|
38
|
+
|
39
|
+
<testsuite name="test.host.ie" package="harcourt">
|
40
|
+
|
41
|
+
<testcase name="1006" time="20" classname="Harcourt">
|
42
|
+
</testcase>
|
43
|
+
|
44
|
+
<testcase name="1007" time="30" classname="Harcourt">
|
45
|
+
<skipped message="not implemented yet"/>
|
46
|
+
</testcase>
|
47
|
+
|
48
|
+
<testcase name="1008" time="50" classname="Harcourt">
|
49
|
+
<failure message="timeout reached"/>
|
50
|
+
<system-out>
|
51
|
+
this is the
|
52
|
+
STDOUT
|
53
|
+
from the
|
54
|
+
system itself
|
55
|
+
</system-out>
|
56
|
+
</testcase>
|
57
|
+
|
58
|
+
</testsuite>
|
59
|
+
</testsuites>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname.new(__dir__).parent + 'lib/jenkins_junit_builder/system_message'
|
3
|
+
require Pathname.new(__dir__).parent + 'lib/jenkins_junit_builder/case'
|
4
|
+
require Pathname.new(__dir__).parent + 'lib/jenkins_junit_builder/suite'
|
5
|
+
require Pathname.new(__dir__).parent + 'lib/jenkins_junit_builder/file_not_found_exception'
|
6
|
+
|
7
|
+
require 'minitest/autorun'
|
8
|
+
require 'minitest/reporters'
|
9
|
+
|
10
|
+
if ENV['MINITEST_REPORTER'] == 'RUBYMINE'
|
11
|
+
Minitest::Reporters.use! Minitest::Reporters::RubyMineReporter.new
|
12
|
+
else
|
13
|
+
Minitest::Reporters.use! Minitest::Reporters::ProgressReporter.new
|
14
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname.new(__dir__) + 'minitest_helper'
|
3
|
+
|
4
|
+
class TestJenkinsJunitBuilder < MiniTest::Test
|
5
|
+
def test_that_it_has_a_version_number
|
6
|
+
refute_nil ::JenkinsJunitBuilder::VERSION
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_system_message_return_value_initialized
|
10
|
+
stack_trace = <<TXT
|
11
|
+
create mode 100644 fonts/helveticaneue/HelveticaNeueItalic.ttf
|
12
|
+
create mode 100644 fonts/helveticaneue/HelveticaNeueLight.ttf
|
13
|
+
create mode 100644 fonts/helveticaneue/HelveticaNeueLightItalic.ttf
|
14
|
+
create mode 100644 fonts/helveticaneue/HelveticaNeueMedium.ttf
|
15
|
+
create mode 100644 fonts/helveticaneue/HelveticaNeueMediumItalic.ttf
|
16
|
+
TXT
|
17
|
+
|
18
|
+
system_out = JenkinsJunitBuilder::SystemMessage.new stack_trace
|
19
|
+
|
20
|
+
assert_equal stack_trace, system_out.to_s, 'System message has not kept the input text in the original form submitted at initialization'
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_system_message_return_value
|
24
|
+
stack_trace = <<TXT
|
25
|
+
Minitest::Skip: Skipped, no message given
|
26
|
+
/home/ikon/src/rocksteady/git/jenkins_junit_builder/test/test_jenkins_junit_builder.rb:39:in `test_building_new_report'
|
27
|
+
|
28
|
+
Minitest::Skip: Skipped, no message given
|
29
|
+
/home/ikon/src/rocksteady/git/jenkins_junit_builder/test/test_jenkins_junit_builder.rb:54:in `test_appending_to_existing_report'
|
30
|
+
Finished in 0.00272s
|
31
|
+
4 tests, 2 assertions, 0 failures, 0 errors, 2 skips
|
32
|
+
TXT
|
33
|
+
|
34
|
+
system_err = JenkinsJunitBuilder::SystemMessage.new
|
35
|
+
system_err.message = stack_trace
|
36
|
+
system_err << 'a new line'
|
37
|
+
|
38
|
+
expected = stack_trace + "\na new line"
|
39
|
+
|
40
|
+
assert_equal expected, system_err.to_s, 'System message has not kept the input text in the original form'
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_building_new_report
|
44
|
+
t_passed = JenkinsJunitBuilder::Case.new
|
45
|
+
t_passed.name = 'My first test case'
|
46
|
+
t_passed.time = 65
|
47
|
+
t_passed.classname = 'FirstTestSuite'
|
48
|
+
t_passed.result = JenkinsJunitBuilder::Case::RESULT_PASSED
|
49
|
+
|
50
|
+
t_failed = JenkinsJunitBuilder::Case.new
|
51
|
+
t_failed.name = 'My failing functionality'
|
52
|
+
t_failed.classname = 'FirstTestSuite'
|
53
|
+
t_failed.result = JenkinsJunitBuilder::Case::RESULT_FAILURE
|
54
|
+
t_failed.message = 'timeout reached'
|
55
|
+
t_failed.system_out.message = 'some thing went wrong'
|
56
|
+
t_failed.system_err.message = 'give me a stacktrace or something'
|
57
|
+
|
58
|
+
t_suite = JenkinsJunitBuilder::Suite.new
|
59
|
+
t_suite.name = 'Testing some cases'
|
60
|
+
t_suite.add_case t_passed
|
61
|
+
t_suite.add_case t_failed
|
62
|
+
|
63
|
+
actual = t_suite.build_report
|
64
|
+
|
65
|
+
expected = <<XML
|
66
|
+
<testsuites>
|
67
|
+
<testsuite name="Testing some cases">
|
68
|
+
<testcase name="My first test case" time="65" classname="FirstTestSuite"/>
|
69
|
+
<testcase name="My failing functionality" classname="FirstTestSuite">
|
70
|
+
<failure message="timeout reached"/>
|
71
|
+
<system-out>some thing went wrong</system-out>
|
72
|
+
<system-err>give me a stacktrace or something</system-err>
|
73
|
+
</testcase>
|
74
|
+
</testsuite>
|
75
|
+
</testsuites>
|
76
|
+
XML
|
77
|
+
expected.strip!
|
78
|
+
|
79
|
+
assert_equal expected, actual
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_dump_file_not_specified
|
83
|
+
assert_raises(JenkinsJunitBuilder::FileNotFoundException) {
|
84
|
+
t_suite = JenkinsJunitBuilder::Suite.new
|
85
|
+
t_suite.write_report_file
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_dump_report_file
|
90
|
+
_report_path = '/tmp/jenkins_junit_builder_test_dump_report_file.xml'
|
91
|
+
|
92
|
+
t_passed = JenkinsJunitBuilder::Case.new
|
93
|
+
t_passed.name = 'My first test case'
|
94
|
+
t_passed.time = 65
|
95
|
+
t_passed.classname = 'FirstTestSuite'
|
96
|
+
t_passed.result = JenkinsJunitBuilder::Case::RESULT_PASSED
|
97
|
+
|
98
|
+
t_failed = JenkinsJunitBuilder::Case.new
|
99
|
+
t_failed.name = 'My failing functionality'
|
100
|
+
t_failed.classname = 'FirstTestSuite'
|
101
|
+
t_failed.result = JenkinsJunitBuilder::Case::RESULT_FAILURE
|
102
|
+
t_failed.message = 'timeout reached'
|
103
|
+
t_failed.system_out.message = 'some thing went wrong'
|
104
|
+
t_failed.system_err.message = 'give me a stacktrace or something'
|
105
|
+
|
106
|
+
t_suite = JenkinsJunitBuilder::Suite.new
|
107
|
+
t_suite.report_path = _report_path
|
108
|
+
t_suite.name = 'Testing some cases'
|
109
|
+
t_suite.add_case t_passed
|
110
|
+
t_suite.add_case t_failed
|
111
|
+
|
112
|
+
actual = t_suite.write_report_file
|
113
|
+
|
114
|
+
expected = <<XML
|
115
|
+
<testsuites>
|
116
|
+
<testsuite name="Testing some cases">
|
117
|
+
<testcase name="My first test case" time="65" classname="FirstTestSuite"/>
|
118
|
+
<testcase name="My failing functionality" classname="FirstTestSuite">
|
119
|
+
<failure message="timeout reached"/>
|
120
|
+
<system-out>some thing went wrong</system-out>
|
121
|
+
<system-err>give me a stacktrace or something</system-err>
|
122
|
+
</testcase>
|
123
|
+
</testsuite>
|
124
|
+
</testsuites>
|
125
|
+
XML
|
126
|
+
expected.strip!
|
127
|
+
|
128
|
+
File::delete _report_path
|
129
|
+
assert_equal expected, actual
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_dump_report_file_appending
|
133
|
+
_report_path = '/tmp/jenkins_junit_builder_test_dump_report_file.xml'
|
134
|
+
|
135
|
+
existing_report_content = <<XML
|
136
|
+
<testsuites>
|
137
|
+
<testsuite name="Testing a case">
|
138
|
+
<testcase name="My zero test case" time="5" classname="FirstTestSuite"/>
|
139
|
+
</testsuite>
|
140
|
+
</testsuites>
|
141
|
+
XML
|
142
|
+
File.write _report_path, existing_report_content
|
143
|
+
|
144
|
+
t_passed = JenkinsJunitBuilder::Case.new
|
145
|
+
t_passed.name = 'My first test case'
|
146
|
+
t_passed.time = 65
|
147
|
+
t_passed.classname = 'FirstTestSuite'
|
148
|
+
t_passed.result = JenkinsJunitBuilder::Case::RESULT_PASSED
|
149
|
+
|
150
|
+
t_failed = JenkinsJunitBuilder::Case.new
|
151
|
+
t_failed.name = 'My failing functionality'
|
152
|
+
t_failed.classname = 'FirstTestSuite'
|
153
|
+
t_failed.result = JenkinsJunitBuilder::Case::RESULT_FAILURE
|
154
|
+
t_failed.message = 'timeout reached'
|
155
|
+
t_failed.system_out.message = 'some thing went wrong'
|
156
|
+
t_failed.system_err.message = 'give me a stacktrace or something'
|
157
|
+
|
158
|
+
t_suite = JenkinsJunitBuilder::Suite.new
|
159
|
+
t_suite.report_path = _report_path
|
160
|
+
t_suite.append_report = true
|
161
|
+
t_suite.name = 'Testing some cases'
|
162
|
+
t_suite.add_case t_passed
|
163
|
+
t_suite.add_case t_failed
|
164
|
+
|
165
|
+
actual = t_suite.write_report_file
|
166
|
+
|
167
|
+
expected = <<XML
|
168
|
+
<testsuites>
|
169
|
+
<testsuite name="Testing a case">
|
170
|
+
<testcase name="My zero test case" time="5" classname="FirstTestSuite"/>
|
171
|
+
</testsuite>
|
172
|
+
<testsuite name="Testing some cases">
|
173
|
+
<testcase name="My first test case" time="65" classname="FirstTestSuite"/>
|
174
|
+
<testcase name="My failing functionality" classname="FirstTestSuite">
|
175
|
+
<failure message="timeout reached"/>
|
176
|
+
<system-out>some thing went wrong</system-out>
|
177
|
+
<system-err>give me a stacktrace or something</system-err>
|
178
|
+
</testcase>
|
179
|
+
</testsuite>
|
180
|
+
</testsuites>
|
181
|
+
XML
|
182
|
+
expected.strip!
|
183
|
+
|
184
|
+
File::delete _report_path
|
185
|
+
assert_equal expected, actual
|
186
|
+
end
|
187
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jenkins_junit_builder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Viktor Vad
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A factory that helps you build Jenkins CI compatible JUnit XML reports
|
56
|
+
for your tests.
|
57
|
+
email:
|
58
|
+
- vad.viktor@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- jenkins_junit.xsd
|
69
|
+
- jenkins_junit_builder.gemspec
|
70
|
+
- lib/jenkins_junit_builder.rb
|
71
|
+
- lib/jenkins_junit_builder/case.rb
|
72
|
+
- lib/jenkins_junit_builder/file_not_found_exception.rb
|
73
|
+
- lib/jenkins_junit_builder/suite.rb
|
74
|
+
- lib/jenkins_junit_builder/system_message.rb
|
75
|
+
- lib/jenkins_junit_builder/version.rb
|
76
|
+
- sample_report.xml
|
77
|
+
- test/minitest_helper.rb
|
78
|
+
- test/test_jenkins_junit_builder.rb
|
79
|
+
homepage: https://github.com/vadviktor/jenkins_junit_builder
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 2.4.5
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Build test reports in Jenkins CI JUnit XML format.
|
103
|
+
test_files:
|
104
|
+
- test/minitest_helper.rb
|
105
|
+
- test/test_jenkins_junit_builder.rb
|