Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec/lib
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-08-03 21:39:48 +0300
committerKamil Trzciński <ayufan@ayufan.eu>2018-08-03 21:39:48 +0300
commit99c033f2888a96267aa0443ad7a07f1f0e861992 (patch)
treea1d7bb68dfaba668987705538bfa4526c473010d /spec/lib
parent53ecd2e147eb24f7e53385cb21f0c9759a482d6c (diff)
parentfafd1764ca71156d261a604d64b43d531667cb17 (diff)
Merge branch 'artifact-format-v2-with-parser' into 'master'
Parse junit.xml.gz and calculate the difference between head and base See merge request gitlab-org/gitlab-ce!20576
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/parsers/junit_spec.rb118
-rw-r--r--spec/lib/gitlab/ci/parsers_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/reports/test_case_spec.rb90
-rw-r--r--spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb134
-rw-r--r--spec/lib/gitlab/ci/reports/test_reports_spec.rb132
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb225
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb120
8 files changed, 898 insertions, 0 deletions
diff --git a/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb b/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb
new file mode 100644
index 00000000000..384329dda18
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Build::Artifacts::GzipFileAdapter do
+ describe '#initialize' do
+ context 'when stream is passed' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
+
+ it 'initialized' do
+ expect { described_class.new(stream) }.not_to raise_error
+ end
+ end
+
+ context 'when stream is not passed' do
+ let(:stream) { nil }
+
+ it 'raises an error' do
+ expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+
+ describe '#each_blob' do
+ let(:adapter) { described_class.new(stream) }
+
+ context 'when stream is gzip file' do
+ context 'when gzip file contains one file' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
+
+ it 'iterates content and file_name' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_with_args(fixture_file('junit/junit.xml'), 'rspec.xml')
+ end
+ end
+
+ context 'when gzip file contains three files' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit_with_three_testsuites.xml.gz'), 'rb') }
+
+ it 'iterates content and file_name' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_successive_args(
+ [fixture_file('junit/junit_with_three_testsuites_1.xml'), 'rspec-3.xml'],
+ [fixture_file('junit/junit_with_three_testsuites_2.xml'), 'rspec-1.xml'],
+ [fixture_file('junit/junit_with_three_testsuites_3.xml'), 'rspec-2.xml'])
+ end
+ end
+ end
+
+ context 'when stream is zip file' do
+ let(:stream) { File.open(expand_fixture_path('ci_build_artifacts.zip'), 'rb') }
+
+ it 'raises an error' do
+ expect { |b| adapter.each_blob(&b) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/junit_spec.rb b/spec/lib/gitlab/ci/parsers/junit_spec.rb
new file mode 100644
index 00000000000..f7ec86f5385
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/junit_spec.rb
@@ -0,0 +1,118 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Parsers::Junit do
+ describe '#parse!' do
+ subject { described_class.new.parse!(junit, test_suite) }
+
+ let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
+ let(:test_cases) { flattened_test_cases(test_suite) }
+
+ context 'when data is JUnit style XML' do
+ context 'when there are no test cases' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite></testsuite>
+ EOF
+ end
+
+ it 'raises an error and does not add any test cases' do
+ expect { subject }.to raise_error(described_class::JunitParserError)
+
+ expect(test_cases.count).to eq(0)
+ end
+ end
+
+ context 'when there is a test case' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ </testsuite>
+ EOF
+ end
+
+ it 'parses XML and adds a test case to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ end
+ end
+
+ context 'when there are two test cases' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
+ </testsuite>
+ EOF
+ end
+
+ it 'parses XML and adds test cases to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ expect(test_cases[1].classname).to eq('Calculator')
+ expect(test_cases[1].name).to eq('sumTest2')
+ expect(test_cases[1].execution_time).to eq(0.02)
+ end
+ end
+
+ context 'when there are two test suites' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
+ </testsuite>
+ <testsuite>
+ <testcase classname='Statemachine' name='happy path' time='100'></testcase>
+ <testcase classname='Statemachine' name='unhappy path' time='200'></testcase>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'parses XML and adds test cases to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ expect(test_cases[1].classname).to eq('Calculator')
+ expect(test_cases[1].name).to eq('sumTest2')
+ expect(test_cases[1].execution_time).to eq(0.02)
+ expect(test_cases[2].classname).to eq('Statemachine')
+ expect(test_cases[2].name).to eq('happy path')
+ expect(test_cases[2].execution_time).to eq(100)
+ expect(test_cases[3].classname).to eq('Statemachine')
+ expect(test_cases[3].name).to eq('unhappy path')
+ expect(test_cases[3].execution_time).to eq(200)
+ end
+ end
+ end
+
+ context 'when data is not JUnit style XML' do
+ let(:junit) { { testsuite: 'abc' }.to_json }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::JunitParserError)
+ end
+ end
+
+ private
+
+ def flattened_test_cases(test_suite)
+ test_suite.test_cases.map do |status, value|
+ value.map do |key, test_case|
+ test_case
+ end
+ end.flatten
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers_spec.rb b/spec/lib/gitlab/ci/parsers_spec.rb
new file mode 100644
index 00000000000..2fa83c4abae
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Parsers do
+ describe '.fabricate!' do
+ subject { described_class.fabricate!(file_type) }
+
+ context 'when file_type exists' do
+ let(:file_type) { 'junit' }
+
+ it 'fabricates the class' do
+ is_expected.to be_a(described_class::Junit)
+ end
+ end
+
+ context 'when file_type does not exist' do
+ let(:file_type) { 'undefined' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(NameError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_case_spec.rb b/spec/lib/gitlab/ci/reports/test_case_spec.rb
new file mode 100644
index 00000000000..6932f79f0ce
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_case_spec.rb
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Reports::TestCase do
+ describe '#initialize' do
+ let(:test_case) { described_class.new(**params)}
+
+ context 'when both classname and name are given' do
+ context 'when test case is passed' do
+ let(:params) do
+ {
+ name: 'test-1',
+ classname: 'trace',
+ file: 'spec/trace_spec.rb',
+ execution_time: 1.23,
+ status: described_class::STATUS_SUCCESS,
+ system_output: nil
+ }
+ end
+
+ it 'initializes an instance' do
+ expect { test_case }.not_to raise_error
+
+ expect(test_case.name).to eq('test-1')
+ expect(test_case.classname).to eq('trace')
+ expect(test_case.file).to eq('spec/trace_spec.rb')
+ expect(test_case.execution_time).to eq(1.23)
+ expect(test_case.status).to eq(described_class::STATUS_SUCCESS)
+ expect(test_case.system_output).to be_nil
+ end
+ end
+
+ context 'when test case is failed' do
+ let(:params) do
+ {
+ name: 'test-1',
+ classname: 'trace',
+ file: 'spec/trace_spec.rb',
+ execution_time: 1.23,
+ status: described_class::STATUS_FAILED,
+ system_output: "Failure/Error: is_expected.to eq(300) expected: 300 got: -100"
+ }
+ end
+
+ it 'initializes an instance' do
+ expect { test_case }.not_to raise_error
+
+ expect(test_case.name).to eq('test-1')
+ expect(test_case.classname).to eq('trace')
+ expect(test_case.file).to eq('spec/trace_spec.rb')
+ expect(test_case.execution_time).to eq(1.23)
+ expect(test_case.status).to eq(described_class::STATUS_FAILED)
+ expect(test_case.system_output)
+ .to eq('Failure/Error: is_expected.to eq(300) expected: 300 got: -100')
+ end
+ end
+ end
+
+ context 'when classname is missing' do
+ let(:params) do
+ {
+ name: 'test-1',
+ file: 'spec/trace_spec.rb',
+ execution_time: 1.23,
+ status: described_class::STATUS_SUCCESS,
+ system_output: nil
+ }
+ end
+
+ it 'raises an error' do
+ expect { test_case }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when name is missing' do
+ let(:params) do
+ {
+ classname: 'trace',
+ file: 'spec/trace_spec.rb',
+ execution_time: 1.23,
+ status: described_class::STATUS_SUCCESS,
+ system_output: nil
+ }
+ end
+
+ it 'raises an error' do
+ expect { test_case }.to raise_error(ArgumentError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb b/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb
new file mode 100644
index 00000000000..71c61e0345f
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_reports_comparer_spec.rb
@@ -0,0 +1,134 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Reports::TestReportsComparer do
+ include TestReportsHelper
+
+ let(:comparer) { described_class.new(base_reports, head_reports) }
+ let(:base_reports) { Gitlab::Ci::Reports::TestReports.new }
+ let(:head_reports) { Gitlab::Ci::Reports::TestReports.new }
+
+ describe '#suite_comparers' do
+ subject { comparer.suite_comparers }
+
+ context 'when head and base reports include two test suites' do
+ before do
+ base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ base_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ end
+
+ it 'returns test suite comparers with specified values' do
+ expect(subject[0]).to be_a(Gitlab::Ci::Reports::TestSuiteComparer)
+ expect(subject[0].name).to eq('rspec')
+ expect(subject[0].head_suite).to eq(head_reports.get_suite('rspec'))
+ expect(subject[0].base_suite).to eq(base_reports.get_suite('rspec'))
+ expect(subject[1]).to be_a(Gitlab::Ci::Reports::TestSuiteComparer)
+ expect(subject[1].name).to eq('junit')
+ expect(subject[1].head_suite).to eq(head_reports.get_suite('junit'))
+ expect(subject[1].base_suite).to eq(base_reports.get_suite('junit'))
+ end
+ end
+ end
+
+ describe '#total_status' do
+ subject { comparer.total_status }
+
+ context 'when all tests cases are success in head suites' do
+ before do
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ end
+
+ it 'returns the total status' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ context 'when there is a failed test case in head suites' do
+ before do
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ end
+
+ it 'returns the total status in head suite' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
+ end
+ end
+ end
+
+ describe '#total_count' do
+ subject { comparer.total_count }
+
+ before do
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ end
+
+ it 'returns the total test counts in head suites' do
+ is_expected.to eq(2)
+ end
+ end
+
+ describe '#resolved_count' do
+ subject { comparer.resolved_count }
+
+ context 'when there is a resolved test case in head suites' do
+ let(:create_test_case_java_resolved) do
+ create_test_case_java_failed.tap do |test_case|
+ test_case.instance_variable_set("@status", Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ before do
+ base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ base_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_resolved)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there are no resolved test cases in head suites' do
+ before do
+ base_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ base_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(0)
+ end
+ end
+ end
+
+ describe '#failed_count' do
+ subject { comparer.failed_count }
+
+ context 'when there is a failed test case in head suites' do
+ before do
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there are no failed test cases in head suites' do
+ before do
+ head_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ head_reports.get_suite('junit').add_test_case(create_test_case_rspec_success)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(0)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_reports_spec.rb b/spec/lib/gitlab/ci/reports/test_reports_spec.rb
new file mode 100644
index 00000000000..74ff134b239
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_reports_spec.rb
@@ -0,0 +1,132 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Reports::TestReports do
+ include TestReportsHelper
+
+ let(:test_reports) { described_class.new }
+
+ describe '#get_suite' do
+ subject { test_reports.get_suite(suite_name) }
+
+ context 'when suite name is rspec' do
+ let(:suite_name) { 'rspec' }
+
+ it { expect(subject.name).to eq('rspec') }
+
+ it 'initializes a new test suite and returns it' do
+ expect(Gitlab::Ci::Reports::TestSuite).to receive(:new).and_call_original
+
+ is_expected.to be_a(Gitlab::Ci::Reports::TestSuite)
+ end
+
+ context 'when suite name is already allocated' do
+ before do
+ subject
+ end
+
+ it 'does not initialize a new test suite' do
+ expect(Gitlab::Ci::Reports::TestSuite).not_to receive(:new)
+
+ is_expected.to be_a(Gitlab::Ci::Reports::TestSuite)
+ end
+ end
+ end
+ end
+
+ describe '#total_time' do
+ subject { test_reports.total_time }
+
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ end
+
+ it 'returns the total time' do
+ is_expected.to eq(6.66)
+ end
+ end
+
+ describe '#total_count' do
+ subject { test_reports.total_count }
+
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ end
+
+ it 'returns the total count' do
+ is_expected.to eq(2)
+ end
+ end
+
+ describe '#total_status' do
+ subject { test_reports.total_status }
+
+ context 'when all test cases succeeded' do
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_success)
+ end
+
+ it 'returns correct total status' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ context 'when there is a failed test case' do
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_failed)
+ end
+
+ it 'returns correct total status' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
+ end
+ end
+
+ context 'when there is a skipped test case' do
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_skipped)
+ end
+
+ it 'returns correct total status' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ context 'when there is an error test case' do
+ before do
+ test_reports.get_suite('rspec').add_test_case(create_test_case_rspec_success)
+ test_reports.get_suite('junit').add_test_case(create_test_case_java_error)
+ end
+
+ it 'returns correct total status' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
+ end
+ end
+ end
+
+ Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
+ describe "##{status_type}_count" do
+ subject { test_reports.public_send("#{status_type}_count") }
+
+ context "when #{status_type} test case exists" do
+ before do
+ test_reports.get_suite('rspec').add_test_case(public_send("create_test_case_rspec_#{status_type}"))
+ test_reports.get_suite('junit').add_test_case(public_send("create_test_case_java_#{status_type}"))
+ end
+
+ it 'returns the count' do
+ is_expected.to eq(2)
+ end
+ end
+
+ context "when #{status_type} test case do not exist" do
+ it 'returns nothing' do
+ is_expected.to be(0)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb
new file mode 100644
index 00000000000..6ab16e5518d
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_suite_comparer_spec.rb
@@ -0,0 +1,225 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Reports::TestSuiteComparer do
+ include TestReportsHelper
+
+ let(:comparer) { described_class.new(name, base_suite, head_suite) }
+ let(:name) { 'rpsec' }
+ let(:base_suite) { Gitlab::Ci::Reports::TestSuite.new(name) }
+ let(:head_suite) { Gitlab::Ci::Reports::TestSuite.new(name) }
+ let(:test_case_success) { create_test_case_rspec_success }
+ let(:test_case_failed) { create_test_case_rspec_failed }
+
+ let(:test_case_resolved) do
+ create_test_case_rspec_failed.tap do |test_case|
+ test_case.instance_variable_set("@status", Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ describe '#new_failures' do
+ subject { comparer.new_failures }
+
+ context 'when head sutie has a newly failed test case which does not exist in base' do
+ before do
+ base_suite.add_test_case(test_case_success)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the failed test case' do
+ is_expected.to eq([test_case_failed])
+ end
+ end
+
+ context 'when head sutie still has a failed test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'does not return the failed test case' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when head sutie has a success test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_resolved)
+ end
+
+ it 'does not return the failed test case' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '#existing_failures' do
+ subject { comparer.existing_failures }
+
+ context 'when head sutie has a newly failed test case which does not exist in base' do
+ before do
+ base_suite.add_test_case(test_case_success)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the failed test case' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when head sutie still has a failed test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'does not return the failed test case' do
+ is_expected.to eq([test_case_failed])
+ end
+ end
+
+ context 'when head sutie has a success test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_resolved)
+ end
+
+ it 'does not return the failed test case' do
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '#resolved_failures' do
+ subject { comparer.resolved_failures }
+
+ context 'when head sutie has a newly failed test case which does not exist in base' do
+ before do
+ base_suite.add_test_case(test_case_success)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the failed test case' do
+ is_expected.to be_empty
+ end
+
+ it 'returns the correct resolved count' do
+ expect(comparer.resolved_count).to eq(0)
+ end
+ end
+
+ context 'when head sutie still has a failed test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'does not return the failed test case' do
+ is_expected.to be_empty
+ end
+
+ it 'returns the correct resolved count' do
+ expect(comparer.resolved_count).to eq(0)
+ end
+ end
+
+ context 'when head sutie has a success test case which failed in base' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_resolved)
+ end
+
+ it 'does not return the resolved test case' do
+ is_expected.to eq([test_case_resolved])
+ end
+
+ it 'returns the correct resolved count' do
+ expect(comparer.resolved_count).to eq(1)
+ end
+ end
+ end
+
+ describe '#total_count' do
+ subject { comparer.total_count }
+
+ before do
+ head_suite.add_test_case(test_case_success)
+ end
+
+ it 'returns the total test counts in head suite' do
+ is_expected.to eq(1)
+ end
+ end
+
+ describe '#failed_count' do
+ subject { comparer.failed_count }
+
+ context 'when there are a new failure and an existing failure' do
+ let(:test_case_1_success) { create_test_case_rspec_success }
+ let(:test_case_2_failed) { create_test_case_rspec_failed }
+
+ let(:test_case_1_failed) do
+ create_test_case_rspec_success.tap do |test_case|
+ test_case.instance_variable_set("@status", Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
+ end
+ end
+
+ before do
+ base_suite.add_test_case(test_case_1_success)
+ base_suite.add_test_case(test_case_2_failed)
+ head_suite.add_test_case(test_case_1_failed)
+ head_suite.add_test_case(test_case_2_failed)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(2)
+ end
+ end
+
+ context 'when there is a new failure' do
+ before do
+ base_suite.add_test_case(test_case_success)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context 'when there is an existing failure' do
+ before do
+ base_suite.add_test_case(test_case_failed)
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the correct count' do
+ is_expected.to eq(1)
+ end
+ end
+ end
+
+ describe '#total_status' do
+ subject { comparer.total_status }
+
+ context 'when all test cases in head suite are success' do
+ before do
+ head_suite.add_test_case(test_case_success)
+ end
+
+ it 'returns the total status in head suite' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
+ end
+ end
+
+ context 'when there is a failed test case in head suite' do
+ before do
+ head_suite.add_test_case(test_case_failed)
+ end
+
+ it 'returns the total status in head suite' do
+ is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
new file mode 100644
index 00000000000..cd34dbaf62f
--- /dev/null
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -0,0 +1,120 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Reports::TestSuite do
+ include TestReportsHelper
+
+ let(:test_suite) { described_class.new('Rspec') }
+ let(:test_case_success) { create_test_case_rspec_success }
+ let(:test_case_failed) { create_test_case_rspec_failed }
+ let(:test_case_skipped) { create_test_case_rspec_skipped }
+ let(:test_case_error) { create_test_case_rspec_error }
+
+ it { expect(test_suite.name).to eq('Rspec') }
+
+ describe '#add_test_case' do
+ context 'when status of the test case is success' do
+ it 'stores data correctly' do
+ test_suite.add_test_case(test_case_success)
+
+ expect(test_suite.test_cases[test_case_success.status][test_case_success.key])
+ .to eq(test_case_success)
+ expect(test_suite.total_time).to eq(1.11)
+ end
+ end
+
+ context 'when status of the test case is failed' do
+ it 'stores data correctly' do
+ test_suite.add_test_case(test_case_failed)
+
+ expect(test_suite.test_cases[test_case_failed.status][test_case_failed.key])
+ .to eq(test_case_failed)
+ expect(test_suite.total_time).to eq(2.22)
+ end
+ end
+
+ context 'when two test cases are added' do
+ it 'sums up total time' do
+ test_suite.add_test_case(test_case_success)
+ test_suite.add_test_case(test_case_failed)
+
+ expect(test_suite.total_time).to eq(3.33)
+ end
+ end
+ end
+
+ describe '#total_count' do
+ subject { test_suite.total_count }
+
+ before do
+ test_suite.add_test_case(test_case_success)
+ test_suite.add_test_case(test_case_failed)
+ end
+
+ it { is_expected.to eq(2) }
+ end
+
+ describe '#total_status' do
+ subject { test_suite.total_status }
+
+ context 'when all test cases succeeded' do
+ before do
+ test_suite.add_test_case(test_case_success)
+ end
+
+ it { is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS) }
+ end
+
+ context 'when a test case failed' do
+ before do
+ test_suite.add_test_case(test_case_success)
+ test_suite.add_test_case(test_case_failed)
+ end
+
+ it { is_expected.to eq(Gitlab::Ci::Reports::TestCase::STATUS_FAILED) }
+ end
+ end
+
+ Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
+ describe "##{status_type}" do
+ subject { test_suite.public_send("#{status_type}") }
+
+ context "when #{status_type} test case exists" do
+ before do
+ test_suite.add_test_case(public_send("test_case_#{status_type}"))
+ end
+
+ it 'returns all success test cases' do
+ is_expected.to eq( { public_send("test_case_#{status_type}").key => public_send("test_case_#{status_type}") })
+ end
+ end
+
+ context "when #{status_type} test case do not exist" do
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+ end
+ end
+ end
+
+ Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
+ describe "##{status_type}_count" do
+ subject { test_suite.public_send("#{status_type}_count") }
+
+ context "when #{status_type} test case exists" do
+ before do
+ test_suite.add_test_case(public_send("test_case_#{status_type}"))
+ end
+
+ it 'returns the count' do
+ is_expected.to eq(1)
+ end
+ end
+
+ context "when #{status_type} test case do not exist" do
+ it 'returns nothing' do
+ is_expected.to be(0)
+ end
+ end
+ end
+ end
+end