diff options
Diffstat (limited to 'qa/spec/tools')
-rw-r--r-- | qa/spec/tools/long_running_spec_reporter_spec.rb | 69 | ||||
-rw-r--r-- | qa/spec/tools/reliable_report_spec.rb | 62 | ||||
-rw-r--r-- | qa/spec/tools/test_resources_data_processor_spec.rb | 33 |
3 files changed, 138 insertions, 26 deletions
diff --git a/qa/spec/tools/long_running_spec_reporter_spec.rb b/qa/spec/tools/long_running_spec_reporter_spec.rb new file mode 100644 index 00000000000..1bf520c53af --- /dev/null +++ b/qa/spec/tools/long_running_spec_reporter_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +RSpec.describe QA::Tools::LongRunningSpecReporter do + include QA::Support::Helpers::StubEnv + + subject(:reporter) { described_class.execute } + + let(:gcs_client) { double("Fog::Storage::GoogleJSON", get_object: report) } + let(:slack_notifier) { double("Slack::Notifier", post: nil) } + + before do + stub_env("SLACK_WEBHOOK", "slack_url") + stub_env("QA_KNAPSACK_REPORT_GCS_CREDENTIALS", "gcs_json") + + allow(Fog::Storage::Google).to receive(:new) + .with(google_project: "gitlab-qa-resources", google_json_key_string: "gcs_json") + .and_return(gcs_client) + allow(Slack::Notifier).to receive(:new) + .with("slack_url", channel: "#quality-reports", username: "Spec Runtime Report") + .and_return(slack_notifier) + end + + context "without specs exceeding runtime" do + let(:report) do + { + body: <<~JSON + { + "spec.rb": 5, + "spec_2.rb": 10 + } + JSON + } + end + + it "returns all good message" do + expect { reporter }.to output("No long running specs detected, all good!\n").to_stdout + end + end + + context "with specs exceeding runtime" do + let(:report) do + { + body: <<~JSON + { + "spec.rb": 5.0, + "spec_2.rb": 320.0 + } + JSON + } + end + + let(:spec) { "spec_2.rb: 5.33 minutes" } + + let(:message) do + <<~MSG + Following spec files are exceeding 5 minute runtime threshold! + Current average spec runtime: 5 seconds. + MSG + end + + it "notifies on long running specs" do + expect { reporter }.to output("#{message}\n#{spec}\n").to_stdout + expect(slack_notifier).to have_received(:post).with( + icon_emoji: ":time-out:", + text: "#{message}\n```#{spec}```" + ) + end + end +end diff --git a/qa/spec/tools/reliable_report_spec.rb b/qa/spec/tools/reliable_report_spec.rb index a048aa2e6ea..1ff62df34e0 100644 --- a/qa/spec/tools/reliable_report_spec.rb +++ b/qa/spec/tools/reliable_report_spec.rb @@ -13,30 +13,43 @@ describe QA::Tools::ReliableReport do let(:slack_channel) { "#quality-reports" } let(:range) { 14 } let(:issue_url) { "https://gitlab.com/issue/1" } + let(:time) { "2021-12-07T04:05:25.000000000+00:00" } let(:runs) do - values = { "name" => "stable spec", "status" => "passed", "file_path" => "some/spec.rb", "stage" => "manage" } + values = { + "name" => "stable spec", + "status" => "passed", + "file_path" => "some/spec.rb", + "stage" => "manage", + "_time" => time + } { 0 => instance_double( "InfluxDB2::FluxTable", records: [ instance_double("InfluxDB2::FluxRecord", values: values), instance_double("InfluxDB2::FluxRecord", values: values), - instance_double("InfluxDB2::FluxRecord", values: values) + instance_double("InfluxDB2::FluxRecord", values: values.merge({ "_time" => Time.now.to_s })) ] ) } end let(:reliable_runs) do - values = { "name" => "unstable spec", "status" => "failed", "file_path" => "some/spec.rb", "stage" => "create" } + values = { + "name" => "unstable spec", + "status" => "failed", + "file_path" => "some/spec.rb", + "stage" => "create", + "_time" => time + } { 0 => instance_double( "InfluxDB2::FluxTable", records: [ instance_double("InfluxDB2::FluxRecord", values: { **values, "status" => "passed" }), instance_double("InfluxDB2::FluxRecord", values: values), - instance_double("InfluxDB2::FluxRecord", values: values) + instance_double("InfluxDB2::FluxRecord", values: values.merge({ "_time" => Time.now.to_s })) ] ) } @@ -67,41 +80,34 @@ describe QA::Tools::ReliableReport do def markdown_section(summary, result, stage, type) <<~SECTION.strip - ``` - #{summary_table(summary, type)} - ``` + #{summary_table(summary, type, true)} - ## #{stage} + ## #{stage} (1) <details> <summary>Executions table</summary> - ``` - #{table(result, ['NAME', 'RUNS', 'FAILURES', 'FAILURE RATE'], "Top #{type} specs in '#{stage}' stage for past #{range} days")} - ``` + #{table(result, ['NAME', 'RUNS', 'FAILURES', 'FAILURE RATE'], "Top #{type} specs in '#{stage}' stage for past #{range} days", true)} </details> SECTION end - def summary_table(summary, type) - table(summary, %w[STAGE COUNT], "#{type.capitalize} spec summary for past #{range} days".ljust(50)) + def summary_table(summary, type, markdown = false) + table(summary, %w[STAGE COUNT], "#{type.capitalize} spec summary for past #{range} days".ljust(50), markdown) end - def table(rows, headings, title) + def table(rows, headings, title, markdown = false) Terminal::Table.new( headings: headings, - style: { all_separators: true }, - title: title, - rows: rows + title: markdown ? nil : title, + rows: rows, + style: markdown ? { border: :markdown } : { all_separators: true } ) end def name_column(spec_name) - name = "name: '#{spec_name}'" - file = "file: 'spec.rb'".ljust(160) - - "#{name}\n#{file}" + "**name**: #{spec_name}<br>**file**: spec.rb" end before do @@ -136,11 +142,15 @@ describe QA::Tools::ReliableReport do <<~TXT.strip [[_TOC_]] - # Candidates for promotion to reliable + # Candidates for promotion to reliable (#{Date.today - range} - #{Date.today}) + + Total amount: **1** #{markdown_section([['manage', 1]], [[name_column('stable spec'), 3, 0, '0%']], 'manage', 'stable')} - # Reliable specs with failures + # Reliable specs with failures (#{Date.today - range} - #{Date.today}) + + Total amount: **1** #{markdown_section([['create', 1]], [[name_column('unstable spec'), 3, 2, '66.67%']], 'create', 'unstable')} TXT @@ -155,9 +165,9 @@ describe QA::Tools::ReliableReport do verify_ssl: false, headers: { "PRIVATE-TOKEN" => "gitlab_token" }, payload: { - title: "Reliable spec report", + title: "Reliable e2e test report", description: issue_body, - labels: "Quality,test" + labels: "Quality,test,type::maintenance,reliable test report" } ) expect(slack_notifier).to have_received(:post).with( @@ -180,7 +190,7 @@ describe QA::Tools::ReliableReport do end it "notifies failure", :aggregate_failures do - expect { expect { run }.to raise_error(SystemExit) }.to output.to_stdout + expect { expect { run }.to raise_error("Connection error!") }.to output.to_stdout expect(slack_notifier).to have_received(:post).with( icon_emoji: ":sadpanda:", diff --git a/qa/spec/tools/test_resources_data_processor_spec.rb b/qa/spec/tools/test_resources_data_processor_spec.rb new file mode 100644 index 00000000000..6a8c0fd06a4 --- /dev/null +++ b/qa/spec/tools/test_resources_data_processor_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +RSpec.describe QA::Tools::TestResourceDataProcessor do + let(:info) { 'information' } + let(:api_path) { '/foo' } + let(:result) { [{ info: info, api_path: api_path }] } + + describe '.collect' do + context 'when resource is not restricted' do + let(:resource) { instance_double(QA::Resource::Project, api_delete_path: '/foo', api_response: 'foo') } + + it 'collects resource' do + expect(described_class.collect(resource, info)).to eq(result) + end + end + + context 'when resource api response is nil' do + let(:resource) { double(QA::Resource::Project, api_delete_path: '/foo', api_response: nil) } + + it 'does not collect resource' do + expect(described_class.collect(resource, info)).to eq(nil) + end + end + + context 'when resource is restricted' do + let(:resource) { double(QA::Resource::Sandbox, api_delete_path: '/foo', api_response: 'foo') } + + it 'does not collect resource' do + expect(described_class.collect(resource, info)).to eq(nil) + end + end + end +end |