Commit 17b5c329 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'mo-add-show-test-suite-endpoint' into 'master'

Expose show tests endpoint

See merge request gitlab-org/gitlab!34886
parents c3d33cd5 cbe21937
...@@ -2,35 +2,58 @@ ...@@ -2,35 +2,58 @@
module Projects module Projects
module Pipelines module Pipelines
class TestsController < Projects::ApplicationController class TestsController < Projects::Pipelines::ApplicationController
before_action :pipeline
before_action :authorize_read_pipeline!
before_action :authorize_read_build!
before_action :validate_feature_flag! before_action :validate_feature_flag!
before_action :authorize_read_build!
before_action :builds, only: [:show]
def summary def summary
respond_to do |format| respond_to do |format|
format.json do format.json do
render json: TestReportSerializer render json: TestReportSummarySerializer
.new(project: project, current_user: @current_user) .new(project: project, current_user: @current_user)
.represent(pipeline.test_report_summary) .represent(pipeline.test_report_summary)
end end
end end
end end
def show
respond_to do |format|
format.json do
render json: TestSuiteSerializer
.new(project: project, current_user: @current_user)
.represent(test_suite, details: true)
end
end
end
private private
def validate_feature_flag! def validate_feature_flag!
render_404 unless Feature.enabled?(:build_report_summary, project) render_404 unless Feature.enabled?(:build_report_summary, project)
end end
def pipeline # rubocop: disable CodeReuse/ActiveRecord
project.all_pipelines.find(tests_params[:id]) def builds
pipeline.latest_builds.where(id: build_params)
end
def build_params
return [] unless params[:build_ids]
params[:build_ids].split(",")
end end
def tests_params def test_suite
params.permit(:id) if builds.present?
builds.map do |build|
build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new)
end.sum
else
render_404
end
end end
# rubocop: enable CodeReuse/ActiveRecord
end end
end end
end end
# frozen_string_literal: true
class TestReportSummaryEntity < TestReportEntity
expose :test_suites, using: TestSuiteSummaryEntity do |summary|
summary.test_suites.values
end
end
# frozen_string_literal: true
class TestReportSummarySerializer < BaseSerializer
entity TestReportSummaryEntity
end
# frozen_string_literal: true
class TestSuiteSerializer < BaseSerializer
entity TestSuiteEntity
end
# frozen_string_literal: true
class TestSuiteSummaryEntity < TestSuiteEntity
expose :build_ids do |summary|
summary.build_ids
end
end
...@@ -26,13 +26,13 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do ...@@ -26,13 +26,13 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do
resources :stages, only: [], param: :name do resources :stages, only: [], param: :name do
post :play_manual post :play_manual
end end
end
resources :tests, only: [], controller: 'pipelines/tests' do resources :tests, only: [:show], param: :suite_name, controller: 'pipelines/tests' do
collection do collection do
get :summary get :summary
end end
end end
end
end end
resources :pipeline_schedules, except: [:show] do resources :pipeline_schedules, except: [:show] do
......
...@@ -4,9 +4,9 @@ module Gitlab ...@@ -4,9 +4,9 @@ module Gitlab
module Ci module Ci
module Reports module Reports
class TestSuite class TestSuite
attr_reader :name attr_accessor :name
attr_reader :test_cases attr_accessor :test_cases
attr_reader :total_time attr_accessor :total_time
attr_reader :suite_error attr_reader :suite_error
def initialize(name = nil) def initialize(name = nil)
...@@ -70,6 +70,14 @@ module Gitlab ...@@ -70,6 +70,14 @@ module Gitlab
@suite_error = msg @suite_error = msg
end end
def +(other)
self.class.new.tap do |test_suite|
test_suite.name = self.name
test_suite.test_cases = self.test_cases.deep_merge(other.test_cases)
test_suite.total_time = self.total_time + other.total_time
end
end
private private
def existing_key?(test_case) def existing_key?(test_case)
......
...@@ -15,6 +15,10 @@ module Gitlab ...@@ -15,6 +15,10 @@ module Gitlab
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def build_ids
results.pluck(:build_id)
end
def total_time def total_time
@total_time ||= results.sum(&:tests_duration) @total_time ||= results.sum(&:tests_duration)
end end
......
...@@ -46,12 +46,66 @@ RSpec.describe Projects::Pipelines::TestsController do ...@@ -46,12 +46,66 @@ RSpec.describe Projects::Pipelines::TestsController do
end end
end end
describe 'GET #show.json' do
context 'when pipeline has build report results' do
let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project) }
let(:suite_name) { 'test' }
let(:build_ids) { pipeline.latest_builds.pluck(:id) }
it 'renders test suite data' do
get_tests_show_json(build_ids)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq('test')
end
end
context 'when pipeline does not have build report results' do
let(:pipeline) { create(:ci_empty_pipeline) }
let(:suite_name) { 'test' }
it 'renders 404' do
get_tests_show_json([])
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to be_empty
end
end
context 'when feature is disabled' do
let(:suite_name) { 'test' }
before do
stub_feature_flags(build_report_summary: false)
end
it 'returns 404' do
get_tests_show_json([])
expect(response).to have_gitlab_http_status(:not_found)
expect(response.body).to be_empty
end
end
end
def get_tests_summary_json def get_tests_summary_json
get :summary, get :summary,
params: { params: {
namespace_id: project.namespace, namespace_id: project.namespace,
project_id: project, project_id: project,
id: pipeline.id pipeline_id: pipeline.id
},
format: :json
end
def get_tests_show_json(build_ids)
get :show,
params: {
namespace_id: project.namespace,
project_id: project,
pipeline_id: pipeline.id,
suite_name: suite_name,
build_ids: build_ids
}, },
format: :json format: :json
end end
......
...@@ -139,6 +139,41 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do ...@@ -139,6 +139,41 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
end end
end end
describe '#+' do
let(:test_suite_2) { described_class.new('Rspec') }
subject { test_suite + test_suite_2 }
context 'when adding multiple suites together' do
before do
test_suite.add_test_case(test_case_success)
test_suite.add_test_case(test_case_failed)
end
it 'returns a new test suite' do
expect(subject).to be_an_instance_of(described_class)
end
it 'returns the suite name' do
expect(subject.name).to eq('Rspec')
end
it 'returns the sum for total_time' do
expect(subject.total_time).to eq(3.33)
end
it 'merges tests cases hash', :aggregate_failures do
test_suite_2.add_test_case(create_test_case_java_success)
failed_keys = test_suite.test_cases['failed'].keys
success_keys = test_suite.test_cases['success'].keys + test_suite_2.test_cases['success'].keys
expect(subject.test_cases['failed'].keys).to contain_exactly(*failed_keys)
expect(subject.test_cases['success'].keys).to contain_exactly(*success_keys)
end
end
end
Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type| Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
describe "##{status_type}" do describe "##{status_type}" do
subject { test_suite.public_send("#{status_type}") } subject { test_suite.public_send("#{status_type}") }
......
...@@ -17,6 +17,16 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteSummary do ...@@ -17,6 +17,16 @@ RSpec.describe Gitlab::Ci::Reports::TestSuiteSummary do
end end
end end
describe '#build_ids' do
subject { test_suite_summary.build_ids }
context 'when test suite summary has several build report results' do
it 'returns the build ids' do
expect(subject).to contain_exactly(build_report_result_1.build_id, build_report_result_2.build_id)
end
end
end
describe '#total_time' do describe '#total_time' do
subject { test_suite_summary.total_time } subject { test_suite_summary.total_time }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe TestReportSummaryEntity do
let(:pipeline) { create(:ci_pipeline, :with_report_results) }
let(:entity) { described_class.new(pipeline.test_report_summary) }
describe '#as_json' do
subject(:as_json) { entity.as_json }
it 'contains the total time' do
expect(as_json).to include(:total_time)
end
it 'contains the counts' do
expect(as_json).to include(:total_count, :success_count, :failed_count, :skipped_count, :error_count)
end
context 'when summary has test suites' do
it 'contains the test suites' do
expect(as_json).to include(:test_suites)
expect(as_json[:test_suites].count).to eq(1)
end
it 'contains build_ids' do
expect(as_json[:test_suites].first).to include(:build_ids)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe TestSuiteSummaryEntity do
let(:pipeline) { create(:ci_pipeline, :with_report_results) }
let(:entity) { described_class.new(pipeline.test_report_summary.total) }
describe '#as_json' do
subject(:as_json) { entity.as_json }
it 'contains the total time' do
expect(as_json).to include(:total_time)
end
it 'contains the counts' do
expect(as_json).to include(:total_count, :success_count, :failed_count, :skipped_count, :error_count)
end
it 'contains the build_ids' do
expect(as_json).to include(:build_ids)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment