Commit 8a0c6dde authored by Daniela Filipe Bento's avatar Daniela Filipe Bento Committed by Patrick Rice
Browse files

feat(api): add support for test report summary api

Changelog: Improvements
parent 8618e137
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ type (
		GetPipeline(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error)
		GetPipelineVariables(pid any, pipeline int, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error)
		GetPipelineTestReport(pid any, pipeline int, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error)
		GetPipelineTestReportSummary(pid any, pipeline int, options ...RequestOptionFunc) (*PipelineTestReportSummary, *Response, error)
		GetLatestPipeline(pid any, opt *GetLatestPipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error)
		CreatePipeline(pid any, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error)
		RetryPipelineBuild(pid any, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error)
@@ -172,6 +173,37 @@ type PipelineTestCases struct {
	RecentFailures *RecentFailures `json:"recent_failures"`
}

// PipelineTestReportSummary contains a summary report of a test run
type PipelineTestReportSummary struct {
	Total      PipelineTotalSummary       `json:"total"`
	TestSuites []PipelineTestSuiteSummary `json:"test_suites"`
}

// PipelineTotalSummary contains a total summary of a test run
type PipelineTotalSummary struct {
	// Documentation examples only show whole numbers, but the test specs for GitLab show decimals, so `float64` is the better attribute here.
	Time       float64 `json:"time"`
	Count      int     `json:"count"`
	Success    int     `json:"success"`
	Failed     int     `json:"failed"`
	Skipped    int     `json:"skipped"`
	Error      int     `json:"error"`
	SuiteError *string `json:"suite_error"`
}

// PipelineTestSuiteSummary contains a test suite summary of a test run
type PipelineTestSuiteSummary struct {
	Name         string  `json:"name"`
	TotalTime    float64 `json:"total_time"`
	TotalCount   int     `json:"total_count"`
	SuccessCount int     `json:"success_count"`
	FailedCount  int     `json:"failed_count"`
	SkippedCount int     `json:"skipped_count"`
	ErrorCount   int     `json:"error_count"`
	BuildIDs     []int   `json:"build_ids"`
	SuiteError   *string `json:"suite_error"`
}

// RecentFailures contains failures count for the project's default branch.
type RecentFailures struct {
	Count      int    `json:"count"`
@@ -325,6 +357,31 @@ func (s *PipelinesService) GetPipelineTestReport(pid any, pipeline int, options
	return p, resp, nil
}

// GetPipelineTestReportSummary gets the test report summary of a single project pipeline.
//
// GitLab API docs:
// https://docs.gitlab.com/api/pipelines/#get-a-test-report-summary-for-a-pipeline
func (s *PipelinesService) GetPipelineTestReportSummary(pid any, pipeline int, options ...RequestOptionFunc) (*PipelineTestReportSummary, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/test_report_summary", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(PipelineTestReportSummary)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, nil
}

// GetLatestPipelineOptions represents the available GetLatestPipeline() options.
//
// GitLab API docs:
+44 −0
Original line number Diff line number Diff line
@@ -180,6 +180,50 @@ func TestGetPipelineTestReport(t *testing.T) {
	}
}

func TestGetPipelineTestReportSummary(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/projects/1/pipelines/123456/test_report_summary", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodGet)
		mustWriteHTTPResponse(t, w, "testdata/get_pipeline_testreport_summary.json")
	})

	testreport, _, err := client.Pipelines.GetPipelineTestReportSummary(1, 123456)
	if err != nil {
		t.Errorf("Pipelines.GetPipelineTestReportSummary returned error: %v", err)
	}

	want := &PipelineTestReportSummary{
		Total: PipelineTotalSummary{
			Time:       1904,
			Count:      3363,
			Success:    3351,
			Failed:     0,
			Skipped:    12,
			Error:      0,
			SuiteError: Ptr("JUnit XML parsing failed: 1:1: FATAL: Document is empty"),
		},
		TestSuites: []PipelineTestSuiteSummary{
			{
				Name:         "test",
				TotalTime:    1904,
				TotalCount:   3363,
				SuccessCount: 3351,
				FailedCount:  0,
				SkippedCount: 12,
				ErrorCount:   0,
				BuildIDs:     []int{66004},
				SuiteError:   Ptr("JUnit XML parsing failed: 1:1: FATAL: Document is empty"),
			},
		},
	}

	if !reflect.DeepEqual(want, testreport) {
		t.Errorf("Pipelines.GetPipelineTestReportSummary returned %+v, want %+v", testreport, want)
	}
}

func TestGetLatestPipeline(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)
+25 −0
Original line number Diff line number Diff line
{
  "total": {
    "time": 1904,
    "count": 3363,
    "success": 3351,
    "failed": 0,
    "skipped": 12,
    "error": 0,
    "suite_error": "JUnit XML parsing failed: 1:1: FATAL: Document is empty"
  },
  "test_suites": [{
            "name": "test",
            "total_time": 1904,
            "total_count": 3363,
            "success_count": 3351,
            "failed_count": 0,
            "skipped_count": 12,
            "error_count": 0,
            "build_ids": [
                66004
            ],
            "suite_error": "JUnit XML parsing failed: 1:1: FATAL: Document is empty"
        }
  ]
}
+45 −0
Original line number Diff line number Diff line
@@ -309,6 +309,51 @@ func (c *MockPipelinesServiceInterfaceGetPipelineTestReportCall) DoAndReturn(f f
	return c
}

// GetPipelineTestReportSummary mocks base method.
func (m *MockPipelinesServiceInterface) GetPipelineTestReportSummary(pid any, pipeline int, options ...gitlab.RequestOptionFunc) (*gitlab.PipelineTestReportSummary, *gitlab.Response, error) {
	m.ctrl.T.Helper()
	varargs := []any{pid, pipeline}
	for _, a := range options {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetPipelineTestReportSummary", varargs...)
	ret0, _ := ret[0].(*gitlab.PipelineTestReportSummary)
	ret1, _ := ret[1].(*gitlab.Response)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetPipelineTestReportSummary indicates an expected call of GetPipelineTestReportSummary.
func (mr *MockPipelinesServiceInterfaceMockRecorder) GetPipelineTestReportSummary(pid, pipeline any, options ...any) *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{pid, pipeline}, options...)
	call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPipelineTestReportSummary", reflect.TypeOf((*MockPipelinesServiceInterface)(nil).GetPipelineTestReportSummary), varargs...)
	return &MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall{Call: call}
}

// MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall wrap *gomock.Call
type MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall struct {
	*gomock.Call
}

// Return rewrite *gomock.Call.Return
func (c *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall) Return(arg0 *gitlab.PipelineTestReportSummary, arg1 *gitlab.Response, arg2 error) *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall {
	c.Call = c.Call.Return(arg0, arg1, arg2)
	return c
}

// Do rewrite *gomock.Call.Do
func (c *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall) Do(f func(any, int, ...gitlab.RequestOptionFunc) (*gitlab.PipelineTestReportSummary, *gitlab.Response, error)) *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall {
	c.Call = c.Call.Do(f)
	return c
}

// DoAndReturn rewrite *gomock.Call.DoAndReturn
func (c *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall) DoAndReturn(f func(any, int, ...gitlab.RequestOptionFunc) (*gitlab.PipelineTestReportSummary, *gitlab.Response, error)) *MockPipelinesServiceInterfaceGetPipelineTestReportSummaryCall {
	c.Call = c.Call.DoAndReturn(f)
	return c
}

// GetPipelineVariables mocks base method.
func (m *MockPipelinesServiceInterface) GetPipelineVariables(pid any, pipeline int, options ...gitlab.RequestOptionFunc) ([]*gitlab.PipelineVariable, *gitlab.Response, error) {
	m.ctrl.T.Helper()