diff --git a/example/weather/services/front/clients/tester/client.go b/example/weather/services/front/clients/tester/client.go index 1ee1c8be..a7dca427 100644 --- a/example/weather/services/front/clients/tester/client.go +++ b/example/weather/services/front/clients/tester/client.go @@ -15,9 +15,10 @@ import ( type ( Client interface { - // Run smoke tests + // Runs ALL API Integration Tests from the Tester service, allowing for filtering on included or excluded tests + TestAll(ctx context.Context, included, excluded []string) (*genfront.TestResults, error) + // Runs API Integration Tests' Smoke Tests ONLY from the Tester service TestSmoke(ctx context.Context) (*genfront.TestResults, error) - TestAll(ctx context.Context, payload *TestAllPayload) (*genfront.TestResults, error) } TestAllPayload struct { @@ -31,6 +32,7 @@ type ( } ) +// Creates a new client for the Tester service. func New(cc *grpc.ClientConn) Client { c := genclient.NewClient(cc, grpc.WaitForReady(true)) return &client{ @@ -39,6 +41,7 @@ func New(cc *grpc.ClientConn) Client { } } +// TestSmoke runs the Smoke collection as defined in func_map.go of the tester service func (c *client) TestSmoke(ctx context.Context) (*genfront.TestResults, error) { res, err := c.testSmoke(ctx, nil) if err != nil { @@ -48,10 +51,12 @@ func (c *client) TestSmoke(ctx context.Context) (*genfront.TestResults, error) { return testerTestResultsToFrontTestResults(res.(*gentester.TestResults)), nil } -func (c *client) TestAll(ctx context.Context, payload *TestAllPayload) (*genfront.TestResults, error) { +// TestAll runs all tests in all collections. Obeys include and exclude filters. +// include and exclude are mutually exclusive and cannot be used together (400 error, bad request) +func (c *client) TestAll(ctx context.Context, included, excluded []string) (*genfront.TestResults, error) { gtPayload := &gentester.TesterPayload{ - Include: payload.Include, - Exclude: payload.Exclude, + Include: included, + Exclude: excluded, } res, err := c.testAll(ctx, gtPayload) if err != nil { diff --git a/example/weather/services/front/clients/tester/mocks/client.go b/example/weather/services/front/clients/tester/mocks/client.go index 644db65b..486cf18c 100644 --- a/example/weather/services/front/clients/tester/mocks/client.go +++ b/example/weather/services/front/clients/tester/mocks/client.go @@ -21,8 +21,8 @@ type ( t *testing.T } + ClientTestAllFunc func(ctx context.Context, included, excluded []string) (*front.TestResults, error) ClientTestSmokeFunc func(ctx context.Context) (*front.TestResults, error) - ClientTestAllFunc func(ctx context.Context, payload *tester.TestAllPayload) (*front.TestResults, error) ) func NewClient(t *testing.T) *Client { @@ -33,37 +33,37 @@ func NewClient(t *testing.T) *Client { return m } -func (m *Client) AddTestSmoke(f ClientTestSmokeFunc) { - m.m.Add("TestSmoke", f) +func (m *Client) AddTestAll(f ClientTestAllFunc) { + m.m.Add("TestAll", f) } -func (m *Client) SetTestSmoke(f ClientTestSmokeFunc) { - m.m.Set("TestSmoke", f) +func (m *Client) SetTestAll(f ClientTestAllFunc) { + m.m.Set("TestAll", f) } -func (m *Client) TestSmoke(ctx context.Context) (*front.TestResults, error) { - if f := m.m.Next("TestSmoke"); f != nil { - return f.(ClientTestSmokeFunc)(ctx) +func (m *Client) TestAll(ctx context.Context, included, excluded []string) (*front.TestResults, error) { + if f := m.m.Next("TestAll"); f != nil { + return f.(ClientTestAllFunc)(ctx, included, excluded) } m.t.Helper() - m.t.Error("unexpected TestSmoke call") + m.t.Error("unexpected TestAll call") return nil, nil } -func (m *Client) AddTestAll(f ClientTestAllFunc) { - m.m.Add("TestAll", f) +func (m *Client) AddTestSmoke(f ClientTestSmokeFunc) { + m.m.Add("TestSmoke", f) } -func (m *Client) SetTestAll(f ClientTestAllFunc) { - m.m.Set("TestAll", f) +func (m *Client) SetTestSmoke(f ClientTestSmokeFunc) { + m.m.Set("TestSmoke", f) } -func (m *Client) TestAll(ctx context.Context, payload *tester.TestAllPayload) (*front.TestResults, error) { - if f := m.m.Next("TestAll"); f != nil { - return f.(ClientTestAllFunc)(ctx, payload) +func (m *Client) TestSmoke(ctx context.Context) (*front.TestResults, error) { + if f := m.m.Next("TestSmoke"); f != nil { + return f.(ClientTestSmokeFunc)(ctx) } m.t.Helper() - m.t.Error("unexpected TestAll call") + m.t.Error("unexpected TestSmoke call") return nil, nil } diff --git a/example/weather/services/front/design/design.go b/example/weather/services/front/design/design.go index 7098170f..160c5b5b 100644 --- a/example/weather/services/front/design/design.go +++ b/example/weather/services/front/design/design.go @@ -26,7 +26,7 @@ var _ = Service("front", func() { }) }) Method("test_all", func() { - Description("Endpoint for running API Integration Tests for the Weather System") + Description("Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests") Payload(func() { Field(1, "include", ArrayOf(String), "Tests to run") Field(2, "exclude", ArrayOf(String), "Tests to exclude") @@ -37,7 +37,7 @@ var _ = Service("front", func() { }) }) Method("test_smoke", func() { - Description("Endpoint for running API Integration Tests for the Weather System") + Description("Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System") Result(TestResults) HTTP(func() { POST("/tester/smoke") diff --git a/example/weather/services/front/design/tester_results.go b/example/weather/services/front/design/tester_results.go index fbd5e566..e1f5e41a 100644 --- a/example/weather/services/front/design/tester_results.go +++ b/example/weather/services/front/design/tester_results.go @@ -6,30 +6,50 @@ import ( var TestResult = Type("TestResult", func() { Description("Test result for a single test") - Field(1, "name", String, "Name of the test") + Field(1, "name", String, "Name of the test", func() { + Example("TestValidIP") + }) Field(2, "passed", Boolean, "Status of the test", func() { Example(true) }) - Field(3, "error", String, "Error message if the test failed") - Field(4, "duration", Int64, "Duration of the test in ns") + Field(3, "error", String, "Error message if the test failed", func() { + Example("error getting location for valid ip: %v") + }) + Field(4, "duration", Int64, "Duration of the test in ms", func() { + Example(1234) + }) Required("name", "passed", "duration") }) var TestCollection = Type("TestCollection", func() { Description("Collection of test results for grouping by service") - Field(1, "name", String, "Name of the test collection") + Field(1, "name", String, "Name of the test collection", func() { + Example("Locator Tests") + }) Field(2, "results", ArrayOf(TestResult), "Test results") - Field(3, "duration", Int64, "Duration of the tests in ns") - Field(4, "pass_count", Int, "Number of tests that passed") - Field(5, "fail_count", Int, "Number of tests that failed") - Required("name", "results", "duration", "pass_count", "fail_count") + Field(3, "duration", Int64, "Duration of the tests in ms", func() { + Example(1234) + }) + Field(4, "pass_count", Int, "Number of tests that passed", func() { + Example(12) + }) + Field(5, "fail_count", Int, "Number of tests that failed", func() { + Example(1) + }) + Required("name", "duration", "pass_count", "fail_count") }) var TestResults = Type("TestResults", func() { Description("Test results for the iam system integration tests") Field(1, "collections", ArrayOf(TestCollection), "Test collections") - Field(2, "duration", Int64, "Duration of the tests in ns") - Field(3, "pass_count", Int, "Number of tests that passed") - Field(4, "fail_count", Int, "Number of tests that failed") + Field(2, "duration", Int64, "Duration of the tests in ms", func() { + Example(1234) + }) + Field(3, "pass_count", Int, "Number of tests that passed", func() { + Example(12) + }) + Field(4, "fail_count", Int, "Number of tests that failed", func() { + Example(1) + }) Required("collections", "duration", "pass_count", "fail_count") }) diff --git a/example/weather/services/front/front.go b/example/weather/services/front/front.go index 187ecef5..8717a4b3 100644 --- a/example/weather/services/front/front.go +++ b/example/weather/services/front/front.go @@ -51,11 +51,12 @@ func (s *Service) Forecast(ctx context.Context, ip string) (*genfront.Forecast2, return &genfront.Forecast2{Location: &loc, Periods: ps}, nil } +// Runs ALL API Integration Tests from the Tester service, allowing for filtering on included or excluded tests func (s *Service) TestAll(ctx context.Context, payload *genfront.TestAllPayload) (*genfront.TestResults, error) { - tcPayload := &tester.TestAllPayload{Include: payload.Include, Exclude: payload.Exclude} - return s.tc.TestAll(ctx, tcPayload) + return s.tc.TestAll(ctx, payload.Include, payload.Exclude) } +// Runs API Integration Tests' Smoke Tests ONLY from the Tester service func (s *Service) TestSmoke(ctx context.Context) (*genfront.TestResults, error) { return s.tc.TestSmoke(ctx) } diff --git a/example/weather/services/front/gen/front/service.go b/example/weather/services/front/gen/front/service.go index a4f45b3a..142fadd1 100644 --- a/example/weather/services/front/gen/front/service.go +++ b/example/weather/services/front/gen/front/service.go @@ -18,9 +18,11 @@ import ( type Service interface { // Retrieve weather forecast for given IP Forecast(context.Context, string) (res *Forecast2, err error) - // Endpoint for running API Integration Tests for the Weather System + // Endpoint for running ALL API Integration Tests for the Weather System, + // allowing for filtering on included or excluded tests TestAll(context.Context, *TestAllPayload) (res *TestResults, err error) - // Endpoint for running API Integration Tests for the Weather System + // Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather + // System TestSmoke(context.Context) (res *TestResults, err error) } @@ -84,7 +86,7 @@ type TestCollection struct { Name string // Test results Results []*TestResult - // Duration of the tests in ns + // Duration of the tests in ms Duration int64 // Number of tests that passed PassCount int @@ -100,7 +102,7 @@ type TestResult struct { Passed bool // Error message if the test failed Error *string - // Duration of the test in ns + // Duration of the test in ms Duration int64 } @@ -108,7 +110,7 @@ type TestResult struct { type TestResults struct { // Test collections Collections []*TestCollection - // Duration of the tests in ns + // Duration of the tests in ms Duration int64 // Number of tests that passed PassCount int diff --git a/example/weather/services/front/gen/http/cli/weather/cli.go b/example/weather/services/front/gen/http/cli/weather/cli.go index 9693647a..bea39597 100644 --- a/example/weather/services/front/gen/http/cli/weather/cli.go +++ b/example/weather/services/front/gen/http/cli/weather/cli.go @@ -153,8 +153,8 @@ Usage: COMMAND: forecast: Retrieve weather forecast for given IP - test-all: Endpoint for running API Integration Tests for the Weather System - test-smoke: Endpoint for running API Integration Tests for the Weather System + test-all: Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests + test-smoke: Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System Additional help: %[1]s front COMMAND --help @@ -174,19 +174,18 @@ Example: func frontTestAllUsage() { fmt.Fprintf(os.Stderr, `%[1]s [flags] front test-all -body JSON -Endpoint for running API Integration Tests for the Weather System +Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests -body JSON: Example: %[1]s front test-all --body '{ "exclude": [ - "Debitis omnis facere.", - "Aliquid dolor corrupti." + "Repudiandae enim molestiae.", + "Ut id iure." ], "include": [ - "Ut id iure.", - "Est quod.", - "Amet maiores repellendus eos." + "Dolor sunt maiores.", + "Asperiores omnis ducimus ad et mollitia." ] }' `, os.Args[0]) @@ -195,7 +194,7 @@ Example: func frontTestSmokeUsage() { fmt.Fprintf(os.Stderr, `%[1]s [flags] front test-smoke -Endpoint for running API Integration Tests for the Weather System +Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System Example: %[1]s front test-smoke diff --git a/example/weather/services/front/gen/http/front/client/cli.go b/example/weather/services/front/gen/http/front/client/cli.go index 41c32292..3cfeb481 100644 --- a/example/weather/services/front/gen/http/front/client/cli.go +++ b/example/weather/services/front/gen/http/front/client/cli.go @@ -23,7 +23,7 @@ func BuildTestAllPayload(frontTestAllBody string) (*front.TestAllPayload, error) { err = json.Unmarshal([]byte(frontTestAllBody), &body) if err != nil { - return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"exclude\": [\n \"Debitis omnis facere.\",\n \"Aliquid dolor corrupti.\"\n ],\n \"include\": [\n \"Ut id iure.\",\n \"Est quod.\",\n \"Amet maiores repellendus eos.\"\n ]\n }'") + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"exclude\": [\n \"Repudiandae enim molestiae.\",\n \"Ut id iure.\"\n ],\n \"include\": [\n \"Dolor sunt maiores.\",\n \"Asperiores omnis ducimus ad et mollitia.\"\n ]\n }'") } } v := &front.TestAllPayload{} diff --git a/example/weather/services/front/gen/http/front/client/encode_decode.go b/example/weather/services/front/gen/http/front/client/encode_decode.go index b459735f..e7ef4462 100644 --- a/example/weather/services/front/gen/http/front/client/encode_decode.go +++ b/example/weather/services/front/gen/http/front/client/encode_decode.go @@ -264,9 +264,11 @@ func unmarshalTestCollectionResponseBodyToFrontTestCollection(v *TestCollectionR PassCount: *v.PassCount, FailCount: *v.FailCount, } - res.Results = make([]*front.TestResult, len(v.Results)) - for i, val := range v.Results { - res.Results[i] = unmarshalTestResultResponseBodyToFrontTestResult(val) + if v.Results != nil { + res.Results = make([]*front.TestResult, len(v.Results)) + for i, val := range v.Results { + res.Results[i] = unmarshalTestResultResponseBodyToFrontTestResult(val) + } } return res @@ -275,6 +277,9 @@ func unmarshalTestCollectionResponseBodyToFrontTestCollection(v *TestCollectionR // unmarshalTestResultResponseBodyToFrontTestResult builds a value of type // *front.TestResult from a value of type *TestResultResponseBody. func unmarshalTestResultResponseBodyToFrontTestResult(v *TestResultResponseBody) *front.TestResult { + if v == nil { + return nil + } res := &front.TestResult{ Name: *v.Name, Passed: *v.Passed, diff --git a/example/weather/services/front/gen/http/front/client/types.go b/example/weather/services/front/gen/http/front/client/types.go index 13e4d59d..dbef249e 100644 --- a/example/weather/services/front/gen/http/front/client/types.go +++ b/example/weather/services/front/gen/http/front/client/types.go @@ -36,7 +36,7 @@ type ForecastResponseBody struct { type TestAllResponseBody struct { // Test collections Collections []*TestCollectionResponseBody `form:"collections,omitempty" json:"collections,omitempty" xml:"collections,omitempty"` - // Duration of the tests in ns + // Duration of the tests in ms Duration *int64 `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` // Number of tests that passed PassCount *int `form:"pass_count,omitempty" json:"pass_count,omitempty" xml:"pass_count,omitempty"` @@ -49,7 +49,7 @@ type TestAllResponseBody struct { type TestSmokeResponseBody struct { // Test collections Collections []*TestCollectionResponseBody `form:"collections,omitempty" json:"collections,omitempty" xml:"collections,omitempty"` - // Duration of the tests in ns + // Duration of the tests in ms Duration *int64 `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` // Number of tests that passed PassCount *int `form:"pass_count,omitempty" json:"pass_count,omitempty" xml:"pass_count,omitempty"` @@ -109,7 +109,7 @@ type TestCollectionResponseBody struct { Name *string `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` // Test results Results []*TestResultResponseBody `form:"results,omitempty" json:"results,omitempty" xml:"results,omitempty"` - // Duration of the tests in ns + // Duration of the tests in ms Duration *int64 `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` // Number of tests that passed PassCount *int `form:"pass_count,omitempty" json:"pass_count,omitempty" xml:"pass_count,omitempty"` @@ -125,7 +125,7 @@ type TestResultResponseBody struct { Passed *bool `form:"passed,omitempty" json:"passed,omitempty" xml:"passed,omitempty"` // Error message if the test failed Error *string `form:"error,omitempty" json:"error,omitempty" xml:"error,omitempty"` - // Duration of the test in ns + // Duration of the test in ms Duration *int64 `form:"duration,omitempty" json:"duration,omitempty" xml:"duration,omitempty"` } @@ -358,9 +358,6 @@ func ValidateTestCollectionResponseBody(body *TestCollectionResponseBody) (err e if body.Name == nil { err = goa.MergeErrors(err, goa.MissingFieldError("name", "body")) } - if body.Results == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("results", "body")) - } if body.Duration == nil { err = goa.MergeErrors(err, goa.MissingFieldError("duration", "body")) } diff --git a/example/weather/services/front/gen/http/front/server/encode_decode.go b/example/weather/services/front/gen/http/front/server/encode_decode.go index b386a808..aea1df2b 100644 --- a/example/weather/services/front/gen/http/front/server/encode_decode.go +++ b/example/weather/services/front/gen/http/front/server/encode_decode.go @@ -168,8 +168,6 @@ func marshalFrontTestCollectionToTestCollectionResponseBody(v *front.TestCollect for i, val := range v.Results { res.Results[i] = marshalFrontTestResultToTestResultResponseBody(val) } - } else { - res.Results = []*TestResultResponseBody{} } return res @@ -178,6 +176,9 @@ func marshalFrontTestCollectionToTestCollectionResponseBody(v *front.TestCollect // marshalFrontTestResultToTestResultResponseBody builds a value of type // *TestResultResponseBody from a value of type *front.TestResult. func marshalFrontTestResultToTestResultResponseBody(v *front.TestResult) *TestResultResponseBody { + if v == nil { + return nil + } res := &TestResultResponseBody{ Name: v.Name, Passed: v.Passed, diff --git a/example/weather/services/front/gen/http/front/server/types.go b/example/weather/services/front/gen/http/front/server/types.go index 10c236b2..ab57d794 100644 --- a/example/weather/services/front/gen/http/front/server/types.go +++ b/example/weather/services/front/gen/http/front/server/types.go @@ -36,7 +36,7 @@ type ForecastResponseBody struct { type TestAllResponseBody struct { // Test collections Collections []*TestCollectionResponseBody `form:"collections" json:"collections" xml:"collections"` - // Duration of the tests in ns + // Duration of the tests in ms Duration int64 `form:"duration" json:"duration" xml:"duration"` // Number of tests that passed PassCount int `form:"pass_count" json:"pass_count" xml:"pass_count"` @@ -49,7 +49,7 @@ type TestAllResponseBody struct { type TestSmokeResponseBody struct { // Test collections Collections []*TestCollectionResponseBody `form:"collections" json:"collections" xml:"collections"` - // Duration of the tests in ns + // Duration of the tests in ms Duration int64 `form:"duration" json:"duration" xml:"duration"` // Number of tests that passed PassCount int `form:"pass_count" json:"pass_count" xml:"pass_count"` @@ -108,8 +108,8 @@ type TestCollectionResponseBody struct { // Name of the test collection Name string `form:"name" json:"name" xml:"name"` // Test results - Results []*TestResultResponseBody `form:"results" json:"results" xml:"results"` - // Duration of the tests in ns + Results []*TestResultResponseBody `form:"results,omitempty" json:"results,omitempty" xml:"results,omitempty"` + // Duration of the tests in ms Duration int64 `form:"duration" json:"duration" xml:"duration"` // Number of tests that passed PassCount int `form:"pass_count" json:"pass_count" xml:"pass_count"` @@ -125,7 +125,7 @@ type TestResultResponseBody struct { Passed bool `form:"passed" json:"passed" xml:"passed"` // Error message if the test failed Error *string `form:"error,omitempty" json:"error,omitempty" xml:"error,omitempty"` - // Duration of the test in ns + // Duration of the test in ms Duration int64 `form:"duration" json:"duration" xml:"duration"` } diff --git a/example/weather/services/front/gen/http/openapi.json b/example/weather/services/front/gen/http/openapi.json index 9d9b9c5e..5613fd41 100644 --- a/example/weather/services/front/gen/http/openapi.json +++ b/example/weather/services/front/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Weather Forecast Service API","description":"The weather forecast service API produces weather forecasts from US-based IPs. It uses IP location to find the appropriate weather station.","version":""},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/forecast/{ip}":{"get":{"tags":["front"],"summary":"forecast front","description":"Retrieve weather forecast for given IP","operationId":"front#forecast","parameters":[{"name":"ip","in":"path","required":true,"type":"string","format":"ip"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontForecastResponseBody","required":["location","periods"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/FrontForecastNotUsaResponseBody"}}},"schemes":["http"]}},"/tester/all":{"post":{"tags":["front"],"summary":"test_all front","description":"Endpoint for running API Integration Tests for the Weather System","operationId":"front#test_all","parameters":[{"name":"test_all_request_body","in":"body","required":true,"schema":{"$ref":"#/definitions/FrontTestAllRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontTestAllResponseBody","required":["collections","duration","pass_count","fail_count"]}}},"schemes":["http"]}},"/tester/smoke":{"post":{"tags":["front"],"summary":"test_smoke front","description":"Endpoint for running API Integration Tests for the Weather System","operationId":"front#test_smoke","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontTestSmokeResponseBody","required":["collections","duration","pass_count","fail_count"]}}},"schemes":["http"]}}},"definitions":{"FrontForecastNotUsaResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":false},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"IP address is not in the US (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"FrontForecastResponseBody":{"title":"FrontForecastResponseBody","type":"object","properties":{"location":{"$ref":"#/definitions/LocationResponseBody"},"periods":{"type":"array","items":{"$ref":"#/definitions/PeriodResponseBody"},"description":"Weather forecast periods","example":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]},"required":["location","periods"]},"FrontTestAllRequestBody":{"title":"FrontTestAllRequestBody","type":"object","properties":{"exclude":{"type":"array","items":{"type":"string","example":"Iste eveniet."},"description":"Tests to exclude","example":["Architecto minima molestiae ad unde.","Porro possimus iste eius minus nesciunt.","Dolores ducimus."]},"include":{"type":"array","items":{"type":"string","example":"Temporibus ex quo nihil rem."},"description":"Tests to run","example":["Et itaque itaque cupiditate voluptas quod.","Sequi ipsum vitae ut impedit.","Officiis asperiores rem consequatur.","Architecto aperiam odit."]}},"example":{"exclude":["Nihil cum.","Amet consequatur.","Quis sint alias."],"include":["Sequi sit molestiae pariatur nam saepe.","Dolorem inventore porro velit.","Iste dolorem.","Quibusdam in dolor error amet ut debitis."]}},"FrontTestAllResponseBody":{"title":"FrontTestAllResponseBody","type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/definitions/TestCollectionResponseBody"},"description":"Test collections","example":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ns","example":8488659046950973621,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":4437501359757801476,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":4542181070557550195,"format":"int64"}},"example":{"collections":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}],"duration":4227364704972892770,"fail_count":677188132726143600,"pass_count":7256829688975880749},"required":["collections","duration","pass_count","fail_count"]},"FrontTestSmokeResponseBody":{"title":"FrontTestSmokeResponseBody","type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/definitions/TestCollectionResponseBody"},"description":"Test collections","example":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ns","example":3276831852005724953,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":7444985474897945228,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":7568645513158539910,"format":"int64"}},"example":{"collections":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}],"duration":3974704679362411249,"fail_count":5538145994199568149,"pass_count":3830990445097321547},"required":["collections","duration","pass_count","fail_count"]},"LocationResponseBody":{"title":"LocationResponseBody","type":"object","properties":{"city":{"type":"string","description":"City","example":"San Francisco"},"lat":{"type":"number","description":"Latitude","example":37.8267,"format":"double"},"long":{"type":"number","description":"Longitude","example":-122.4233,"format":"double"},"state":{"type":"string","description":"State","example":"CA"}},"description":"Geographical location","example":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"required":["lat","long","city","state"]},"PeriodResponseBody":{"title":"PeriodResponseBody","type":"object","properties":{"endTime":{"type":"string","description":"End time","example":"2020-01-01T00:00:00Z","format":"date-time"},"name":{"type":"string","description":"Period name","example":"Morning"},"startTime":{"type":"string","description":"Start time","example":"2020-01-01T00:00:00Z","format":"date-time"},"summary":{"type":"string","description":"Summary","example":"Clear"},"temperature":{"type":"integer","description":"Temperature","example":70,"format":"int64"},"temperatureUnit":{"type":"string","description":"Temperature unit","example":"F"}},"description":"Weather forecast period","example":{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},"required":["name","startTime","endTime","temperature","temperatureUnit","summary"]},"TestCollectionResponseBody":{"title":"TestCollectionResponseBody","type":"object","properties":{"duration":{"type":"integer","description":"Duration of the tests in ns","example":8853997182033955550,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1059133839524475990,"format":"int64"},"name":{"type":"string","description":"Name of the test collection","example":"Vel inventore."},"pass_count":{"type":"integer","description":"Number of tests that passed","example":5893583093005980628,"format":"int64"},"results":{"type":"array","items":{"$ref":"#/definitions/TestResultResponseBody"},"description":"Test results","example":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}},"description":"Collection of test results for grouping by service","example":{"duration":8938474736767396736,"fail_count":5612515089578572696,"name":"Sit quis aut deleniti tenetur.","pass_count":7491432401091584119,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},"required":["name","results","duration","pass_count","fail_count"]},"TestResultResponseBody":{"title":"TestResultResponseBody","type":"object","properties":{"duration":{"type":"integer","description":"Duration of the test in ns","example":4825182501324116159,"format":"int64"},"error":{"type":"string","description":"Error message if the test failed","example":"Tempora tenetur."},"name":{"type":"string","description":"Name of the test","example":"Ab nulla ad in optio sed."},"passed":{"type":"boolean","description":"Status of the test","example":true}},"description":"Test result for a single test","example":{"duration":6032363257340067070,"error":"Omnis vel quia ab dolorem qui.","name":"Asperiores est.","passed":true},"required":["name","passed","duration"]}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Weather Forecast Service API","description":"The weather forecast service API produces weather forecasts from US-based IPs. It uses IP location to find the appropriate weather station.","version":""},"host":"localhost:80","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/forecast/{ip}":{"get":{"tags":["front"],"summary":"forecast front","description":"Retrieve weather forecast for given IP","operationId":"front#forecast","parameters":[{"name":"ip","in":"path","required":true,"type":"string","format":"ip"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontForecastResponseBody","required":["location","periods"]}},"400":{"description":"Bad Request response.","schema":{"$ref":"#/definitions/FrontForecastNotUsaResponseBody"}}},"schemes":["http"]}},"/tester/all":{"post":{"tags":["front"],"summary":"test_all front","description":"Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests","operationId":"front#test_all","parameters":[{"name":"test_all_request_body","in":"body","required":true,"schema":{"$ref":"#/definitions/FrontTestAllRequestBody"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontTestAllResponseBody","required":["collections","duration","pass_count","fail_count"]}}},"schemes":["http"]}},"/tester/smoke":{"post":{"tags":["front"],"summary":"test_smoke front","description":"Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System","operationId":"front#test_smoke","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/FrontTestSmokeResponseBody","required":["collections","duration","pass_count","fail_count"]}}},"schemes":["http"]}}},"definitions":{"FrontForecastNotUsaResponseBody":{"title":"Mediatype identifier: application/vnd.goa.error; view=default","type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"IP address is not in the US (default view)","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":true},"required":["name","id","message","temporary","timeout","fault"]},"FrontForecastResponseBody":{"title":"FrontForecastResponseBody","type":"object","properties":{"location":{"$ref":"#/definitions/LocationResponseBody"},"periods":{"type":"array","items":{"$ref":"#/definitions/PeriodResponseBody"},"description":"Weather forecast periods","example":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]},"required":["location","periods"]},"FrontTestAllRequestBody":{"title":"FrontTestAllRequestBody","type":"object","properties":{"exclude":{"type":"array","items":{"type":"string","example":"Eos nihil accusamus reiciendis eligendi amet aut."},"description":"Tests to exclude","example":["Hic aperiam.","Assumenda commodi aut facilis."]},"include":{"type":"array","items":{"type":"string","example":"Corrupti dignissimos id necessitatibus consequatur a laudantium."},"description":"Tests to run","example":["Nihil voluptatum dolorem nam quisquam.","Incidunt ipsa natus."]}},"example":{"exclude":["Asperiores est.","Omnis vel quia ab dolorem qui.","Dicta fuga praesentium.","Est sit quis."],"include":["Aspernatur voluptatem et placeat deserunt.","Temporibus veritatis vel.","Voluptatem ab nulla ad in optio sed.","Tempora tenetur."]}},"FrontTestAllResponseBody":{"title":"FrontTestAllResponseBody","type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/definitions/TestCollectionResponseBody"},"description":"Test collections","example":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ms","example":1234,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":12,"format":"int64"}},"example":{"collections":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}],"duration":1234,"fail_count":1,"pass_count":12},"required":["collections","duration","pass_count","fail_count"]},"FrontTestSmokeResponseBody":{"title":"FrontTestSmokeResponseBody","type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/definitions/TestCollectionResponseBody"},"description":"Test collections","example":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ms","example":1234,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":12,"format":"int64"}},"example":{"collections":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}],"duration":1234,"fail_count":1,"pass_count":12},"required":["collections","duration","pass_count","fail_count"]},"LocationResponseBody":{"title":"LocationResponseBody","type":"object","properties":{"city":{"type":"string","description":"City","example":"San Francisco"},"lat":{"type":"number","description":"Latitude","example":37.8267,"format":"double"},"long":{"type":"number","description":"Longitude","example":-122.4233,"format":"double"},"state":{"type":"string","description":"State","example":"CA"}},"description":"Geographical location","example":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"required":["lat","long","city","state"]},"PeriodResponseBody":{"title":"PeriodResponseBody","type":"object","properties":{"endTime":{"type":"string","description":"End time","example":"2020-01-01T00:00:00Z","format":"date-time"},"name":{"type":"string","description":"Period name","example":"Morning"},"startTime":{"type":"string","description":"Start time","example":"2020-01-01T00:00:00Z","format":"date-time"},"summary":{"type":"string","description":"Summary","example":"Clear"},"temperature":{"type":"integer","description":"Temperature","example":70,"format":"int64"},"temperatureUnit":{"type":"string","description":"Temperature unit","example":"F"}},"description":"Weather forecast period","example":{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},"required":["name","startTime","endTime","temperature","temperatureUnit","summary"]},"TestCollectionResponseBody":{"title":"TestCollectionResponseBody","type":"object","properties":{"duration":{"type":"integer","description":"Duration of the tests in ms","example":1234,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1,"format":"int64"},"name":{"type":"string","description":"Name of the test collection","example":"Locator Tests"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":12,"format":"int64"},"results":{"type":"array","items":{"$ref":"#/definitions/TestResultResponseBody"},"description":"Test results","example":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}},"description":"Collection of test results for grouping by service","example":{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},"required":["name","duration","pass_count","fail_count"]},"TestResultResponseBody":{"title":"TestResultResponseBody","type":"object","properties":{"duration":{"type":"integer","description":"Duration of the test in ms","example":1234,"format":"int64"},"error":{"type":"string","description":"Error message if the test failed","example":"error getting location for valid ip: %v"},"name":{"type":"string","description":"Name of the test","example":"TestValidIP"},"passed":{"type":"boolean","description":"Status of the test","example":true}},"description":"Test result for a single test","example":{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},"required":["name","passed","duration"]}}} \ No newline at end of file diff --git a/example/weather/services/front/gen/http/openapi.yaml b/example/weather/services/front/gen/http/openapi.yaml index c46ba751..81ed6922 100644 --- a/example/weather/services/front/gen/http/openapi.yaml +++ b/example/weather/services/front/gen/http/openapi.yaml @@ -45,7 +45,7 @@ paths: tags: - front summary: test_all front - description: Endpoint for running API Integration Tests for the Weather System + description: Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests operationId: front#test_all parameters: - name: test_all_request_body @@ -70,7 +70,7 @@ paths: tags: - front summary: test_smoke front - description: Endpoint for running API Integration Tests for the Weather System + description: Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System operationId: front#test_smoke responses: "200": @@ -92,7 +92,7 @@ definitions: fault: type: boolean description: Is the error a server-side fault? - example: false + example: true id: type: string description: ID is a unique identifier for this particular occurrence of the problem. @@ -108,7 +108,7 @@ definitions: temporary: type: boolean description: Is the error temporary? - example: false + example: true timeout: type: boolean description: Is the error a timeout? @@ -120,7 +120,7 @@ definitions: message: parameter 'p' must be an integer name: bad_request temporary: true - timeout: false + timeout: true required: - name - id @@ -152,6 +152,18 @@ definitions: summary: Clear temperature: 70 temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F example: location: city: San Francisco @@ -177,6 +189,12 @@ definitions: summary: Clear temperature: 70 temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F required: - location - periods @@ -188,33 +206,31 @@ definitions: type: array items: type: string - example: Iste eveniet. + example: Eos nihil accusamus reiciendis eligendi amet aut. description: Tests to exclude example: - - Architecto minima molestiae ad unde. - - Porro possimus iste eius minus nesciunt. - - Dolores ducimus. + - Hic aperiam. + - Assumenda commodi aut facilis. include: type: array items: type: string - example: Temporibus ex quo nihil rem. + example: Corrupti dignissimos id necessitatibus consequatur a laudantium. description: Tests to run example: - - Et itaque itaque cupiditate voluptas quod. - - Sequi ipsum vitae ut impedit. - - Officiis asperiores rem consequatur. - - Architecto aperiam odit. + - Nihil voluptatum dolorem nam quisquam. + - Incidunt ipsa natus. example: exclude: - - Nihil cum. - - Amet consequatur. - - Quis sint alias. + - Asperiores est. + - Omnis vel quia ab dolorem qui. + - Dicta fuga praesentium. + - Est sit quis. include: - - Sequi sit molestiae pariatur nam saepe. - - Dolorem inventore porro velit. - - Iste dolorem. - - Quibusdam in dolor error amet ut debitis. + - Aspernatur voluptatem et placeat deserunt. + - Temporibus veritatis vel. + - Voluptatem ab nulla ad in optio sed. + - Tempora tenetur. FrontTestAllResponseBody: title: FrontTestAllResponseBody type: object @@ -225,173 +241,91 @@ definitions: $ref: '#/definitions/TestCollectionResponseBody' description: Test collections example: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 - results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 - results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true duration: type: integer - description: Duration of the tests in ns - example: 8488659046950973621 + description: Duration of the tests in ms + example: 1234 format: int64 fail_count: type: integer description: Number of tests that failed - example: 4437501359757801476 + example: 1 format: int64 pass_count: type: integer description: Number of tests that passed - example: 4542181070557550195 + example: 12 format: int64 example: collections: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - duration: 4227364704972892770 - fail_count: 677188132726143600 - pass_count: 7256829688975880749 + duration: 1234 + fail_count: 1 + pass_count: 12 required: - collections - duration @@ -407,152 +341,104 @@ definitions: $ref: '#/definitions/TestCollectionResponseBody' description: Test collections example: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true duration: type: integer - description: Duration of the tests in ns - example: 3276831852005724953 + description: Duration of the tests in ms + example: 1234 format: int64 fail_count: type: integer description: Number of tests that failed - example: 7444985474897945228 + example: 1 format: int64 pass_count: type: integer description: Number of tests that passed - example: 7568645513158539910 + example: 12 format: int64 example: collections: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - duration: 3974704679362411249 - fail_count: 5538145994199568149 - pass_count: 3830990445097321547 + duration: 1234 + fail_count: 1 + pass_count: 12 required: - collections - duration @@ -643,22 +529,22 @@ definitions: properties: duration: type: integer - description: Duration of the tests in ns - example: 8853997182033955550 + description: Duration of the tests in ms + example: 1234 format: int64 fail_count: type: integer description: Number of tests that failed - example: 1059133839524475990 + example: 1 format: int64 name: type: string description: Name of the test collection - example: Vel inventore. + example: Locator Tests pass_count: type: integer description: Number of tests that passed - example: 5893583093005980628 + example: 12 format: int64 results: type: array @@ -666,48 +552,39 @@ definitions: $ref: '#/definitions/TestResultResponseBody' description: Test results example: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true description: Collection of test results for grouping by service example: - duration: 8938474736767396736 - fail_count: 5612515089578572696 - name: Sit quis aut deleniti tenetur. - pass_count: 7491432401091584119 + duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true required: - name - - results - duration - pass_count - fail_count @@ -717,26 +594,26 @@ definitions: properties: duration: type: integer - description: Duration of the test in ns - example: 4825182501324116159 + description: Duration of the test in ms + example: 1234 format: int64 error: type: string description: Error message if the test failed - example: Tempora tenetur. + example: 'error getting location for valid ip: %v' name: type: string description: Name of the test - example: Ab nulla ad in optio sed. + example: TestValidIP passed: type: boolean description: Status of the test example: true description: Test result for a single test example: - duration: 6032363257340067070 - error: Omnis vel quia ab dolorem qui. - name: Asperiores est. + duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true required: - name diff --git a/example/weather/services/front/gen/http/openapi3.json b/example/weather/services/front/gen/http/openapi3.json index e2f0de17..f4e14180 100644 --- a/example/weather/services/front/gen/http/openapi3.json +++ b/example/weather/services/front/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Weather Forecast Service API","description":"The weather forecast service API produces weather forecasts from US-based IPs. It uses IP location to find the appropriate weather station.","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for Weather"}],"paths":{"/forecast/{ip}":{"get":{"tags":["front"],"summary":"forecast front","description":"Retrieve weather forecast for given IP","operationId":"front#forecast","parameters":[{"name":"ip","in":"path","required":true,"schema":{"type":"string","example":"252.22.98.98","format":"ip"},"example":"173.107.152.250"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Forecast"},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}}}},"400":{"description":"not_usa: IP address is not in the US","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tester/all":{"post":{"tags":["front"],"summary":"test_all front","description":"Endpoint for running API Integration Tests for the Weather System","operationId":"front#test_all","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestAllRequestBody"},"example":{"exclude":["Debitis omnis facere.","Aliquid dolor corrupti."],"include":["Ut id iure.","Est quod.","Amet maiores repellendus eos."]}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResults"},"example":{"collections":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}],"duration":6968490088250328124,"fail_count":3063074147820472067,"pass_count":6067631605511723254}}}}}}},"/tester/smoke":{"post":{"tags":["front"],"summary":"test_smoke front","description":"Endpoint for running API Integration Tests for the Weather System","operationId":"front#test_smoke","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResults"},"example":{"collections":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}],"duration":9154617995926910546,"fail_count":8279783259458611454,"pass_count":3830585010251827564}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":false},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":true}},"description":"IP address is not in the US","example":{"fault":true,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"Forecast":{"type":"object","properties":{"location":{"$ref":"#/components/schemas/Location"},"periods":{"type":"array","items":{"$ref":"#/components/schemas/Period"},"description":"Weather forecast periods","example":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]},"required":["location","periods"]},"Location":{"type":"object","properties":{"city":{"type":"string","description":"City","example":"San Francisco"},"lat":{"type":"number","description":"Latitude","example":37.8267,"format":"double"},"long":{"type":"number","description":"Longitude","example":-122.4233,"format":"double"},"state":{"type":"string","description":"State","example":"CA"}},"description":"Geographical location","example":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"required":["lat","long","city","state"]},"Period":{"type":"object","properties":{"endTime":{"type":"string","description":"End time","example":"2020-01-01T00:00:00Z","format":"date-time"},"name":{"type":"string","description":"Period name","example":"Morning"},"startTime":{"type":"string","description":"Start time","example":"2020-01-01T00:00:00Z","format":"date-time"},"summary":{"type":"string","description":"Summary","example":"Clear"},"temperature":{"type":"integer","description":"Temperature","example":70,"format":"int64"},"temperatureUnit":{"type":"string","description":"Temperature unit","example":"F"}},"description":"Weather forecast period","example":{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},"required":["name","startTime","endTime","temperature","temperatureUnit","summary"]},"TestAllRequestBody":{"type":"object","properties":{"exclude":{"type":"array","items":{"type":"string","example":"Accusamus pariatur."},"description":"Tests to exclude","example":["Ad sit in.","Id et doloribus pariatur et.","Exercitationem tempore."]},"include":{"type":"array","items":{"type":"string","example":"Exercitationem praesentium et."},"description":"Tests to run","example":["Aut sed mollitia.","Numquam recusandae omnis occaecati sint praesentium est."]}},"example":{"exclude":["Modi omnis sed.","Id consequatur alias vitae voluptas quia."],"include":["Doloremque et.","Officia voluptates."]}},"TestCollection":{"type":"object","properties":{"duration":{"type":"integer","description":"Duration of the tests in ns","example":2079009122591064687,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":295202760764443778,"format":"int64"},"name":{"type":"string","description":"Name of the test collection","example":"Consequatur omnis ea."},"pass_count":{"type":"integer","description":"Number of tests that passed","example":6357848907083386262,"format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TestResult"},"description":"Test results","example":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}},"description":"Collection of test results for grouping by service","example":{"duration":1981842416553121767,"fail_count":8707465760791589491,"name":"Inventore quae aspernatur quia.","pass_count":936953043246880977,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},"required":["name","results","duration","pass_count","fail_count"]},"TestResult":{"type":"object","properties":{"duration":{"type":"integer","description":"Duration of the test in ns","example":7518210316316224812,"format":"int64"},"error":{"type":"string","description":"Error message if the test failed","example":"Dolor velit voluptates esse nesciunt eos et."},"name":{"type":"string","description":"Name of the test","example":"Non voluptas ex itaque rerum totam possimus."},"passed":{"type":"boolean","description":"Status of the test","example":true}},"description":"Test result for a single test","example":{"duration":2636828426958641278,"error":"Sint accusantium est quisquam vitae modi est.","name":"Voluptatem sit consectetur perferendis corrupti ipsam non.","passed":true},"required":["name","passed","duration"]},"TestResults":{"type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/components/schemas/TestCollection"},"description":"Test collections","example":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ns","example":6542909308659190311,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":5090292743939825689,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":4885942239601822760,"format":"int64"}},"example":{"collections":[{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]},{"duration":9054733701520478298,"fail_count":7502424151970560367,"name":"Id necessitatibus consequatur a laudantium quia qui.","pass_count":8417812319446678629,"results":[{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true},{"duration":859505013544304124,"error":"Consectetur eos nihil accusamus reiciendis eligendi.","name":"Dolorem nam quisquam laudantium incidunt ipsa.","passed":true}]}],"duration":6479921303740404391,"fail_count":6775673673163648586,"pass_count":921268878604032922},"required":["collections","duration","pass_count","fail_count"]}}},"tags":[{"name":"front","description":"Public HTTP frontend"}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Weather Forecast Service API","description":"The weather forecast service API produces weather forecasts from US-based IPs. It uses IP location to find the appropriate weather station.","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for Weather"}],"paths":{"/forecast/{ip}":{"get":{"tags":["front"],"summary":"forecast front","description":"Retrieve weather forecast for given IP","operationId":"front#forecast","parameters":[{"name":"ip","in":"path","required":true,"schema":{"type":"string","example":"137.67.93.10","format":"ip"},"example":"57.127.156.27"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Forecast"},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}}}},"400":{"description":"not_usa: IP address is not in the US","content":{"application/vnd.goa.error":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tester/all":{"post":{"tags":["front"],"summary":"test_all front","description":"Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests","operationId":"front#test_all","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestAllRequestBody"},"example":{"exclude":["Repudiandae enim molestiae.","Ut id iure."],"include":["Dolor sunt maiores.","Asperiores omnis ducimus ad et mollitia."]}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResults"},"example":{"collections":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}],"duration":1234,"fail_count":1,"pass_count":12}}}}}}},"/tester/smoke":{"post":{"tags":["front"],"summary":"test_smoke front","description":"Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System","operationId":"front#test_smoke","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResults"},"example":{"collections":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}],"duration":1234,"fail_count":1,"pass_count":12}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"fault":{"type":"boolean","description":"Is the error a server-side fault?","example":true},"id":{"type":"string","description":"ID is a unique identifier for this particular occurrence of the problem.","example":"123abc"},"message":{"type":"string","description":"Message is a human-readable explanation specific to this occurrence of the problem.","example":"parameter 'p' must be an integer"},"name":{"type":"string","description":"Name is the name of this class of errors.","example":"bad_request"},"temporary":{"type":"boolean","description":"Is the error temporary?","example":true},"timeout":{"type":"boolean","description":"Is the error a timeout?","example":false}},"description":"IP address is not in the US","example":{"fault":false,"id":"123abc","message":"parameter 'p' must be an integer","name":"bad_request","temporary":true,"timeout":false},"required":["name","id","message","temporary","timeout","fault"]},"Forecast":{"type":"object","properties":{"location":{"$ref":"#/components/schemas/Location"},"periods":{"type":"array","items":{"$ref":"#/components/schemas/Period"},"description":"Weather forecast periods","example":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]}},"example":{"location":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"periods":[{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"}]},"required":["location","periods"]},"Location":{"type":"object","properties":{"city":{"type":"string","description":"City","example":"San Francisco"},"lat":{"type":"number","description":"Latitude","example":37.8267,"format":"double"},"long":{"type":"number","description":"Longitude","example":-122.4233,"format":"double"},"state":{"type":"string","description":"State","example":"CA"}},"description":"Geographical location","example":{"city":"San Francisco","lat":37.8267,"long":-122.4233,"state":"CA"},"required":["lat","long","city","state"]},"Period":{"type":"object","properties":{"endTime":{"type":"string","description":"End time","example":"2020-01-01T00:00:00Z","format":"date-time"},"name":{"type":"string","description":"Period name","example":"Morning"},"startTime":{"type":"string","description":"Start time","example":"2020-01-01T00:00:00Z","format":"date-time"},"summary":{"type":"string","description":"Summary","example":"Clear"},"temperature":{"type":"integer","description":"Temperature","example":70,"format":"int64"},"temperatureUnit":{"type":"string","description":"Temperature unit","example":"F"}},"description":"Weather forecast period","example":{"endTime":"2020-01-01T00:00:00Z","name":"Morning","startTime":"2020-01-01T00:00:00Z","summary":"Clear","temperature":70,"temperatureUnit":"F"},"required":["name","startTime","endTime","temperature","temperatureUnit","summary"]},"TestAllRequestBody":{"type":"object","properties":{"exclude":{"type":"array","items":{"type":"string","example":"Cupiditate voluptas quod minima."},"description":"Tests to exclude","example":["Vitae ut.","Non officiis asperiores rem."]},"include":{"type":"array","items":{"type":"string","example":"Sed officia cum."},"description":"Tests to run","example":["Temporibus ex quo nihil rem.","Et et itaque."]}},"example":{"exclude":["Architecto minima molestiae ad unde.","Porro possimus iste eius minus nesciunt.","Dolores ducimus."],"include":["Architecto aperiam odit.","Iste eveniet."]}},"TestCollection":{"type":"object","properties":{"duration":{"type":"integer","description":"Duration of the tests in ms","example":1234,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1,"format":"int64"},"name":{"type":"string","description":"Name of the test collection","example":"Locator Tests"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":12,"format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/TestResult"},"description":"Test results","example":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}},"description":"Collection of test results for grouping by service","example":{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},"required":["name","duration","pass_count","fail_count"]},"TestResult":{"type":"object","properties":{"duration":{"type":"integer","description":"Duration of the test in ms","example":1234,"format":"int64"},"error":{"type":"string","description":"Error message if the test failed","example":"error getting location for valid ip: %v"},"name":{"type":"string","description":"Name of the test","example":"TestValidIP"},"passed":{"type":"boolean","description":"Status of the test","example":true}},"description":"Test result for a single test","example":{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},"required":["name","passed","duration"]},"TestResults":{"type":"object","properties":{"collections":{"type":"array","items":{"$ref":"#/components/schemas/TestCollection"},"description":"Test collections","example":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}]},"duration":{"type":"integer","description":"Duration of the tests in ms","example":1234,"format":"int64"},"fail_count":{"type":"integer","description":"Number of tests that failed","example":1,"format":"int64"},"pass_count":{"type":"integer","description":"Number of tests that passed","example":12,"format":"int64"}},"example":{"collections":[{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]},{"duration":1234,"fail_count":1,"name":"Locator Tests","pass_count":12,"results":[{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true},{"duration":1234,"error":"error getting location for valid ip: %v","name":"TestValidIP","passed":true}]}],"duration":1234,"fail_count":1,"pass_count":12},"required":["collections","duration","pass_count","fail_count"]}}},"tags":[{"name":"front","description":"Public HTTP frontend"}]} \ No newline at end of file diff --git a/example/weather/services/front/gen/http/openapi3.yaml b/example/weather/services/front/gen/http/openapi3.yaml index f51acfb9..ff15b025 100644 --- a/example/weather/services/front/gen/http/openapi3.yaml +++ b/example/weather/services/front/gen/http/openapi3.yaml @@ -20,9 +20,9 @@ paths: required: true schema: type: string - example: 252.22.98.98 + example: 137.67.93.10 format: ip - example: 173.107.152.250 + example: 57.127.156.27 responses: "200": description: OK response. @@ -49,6 +49,18 @@ paths: summary: Clear temperature: 70 temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F "400": description: 'not_usa: IP address is not in the US' content: @@ -60,7 +72,7 @@ paths: tags: - front summary: test_all front - description: Endpoint for running API Integration Tests for the Weather System + description: Endpoint for running ALL API Integration Tests for the Weather System, allowing for filtering on included or excluded tests operationId: front#test_all requestBody: required: true @@ -70,12 +82,11 @@ paths: $ref: '#/components/schemas/TestAllRequestBody' example: exclude: - - Debitis omnis facere. - - Aliquid dolor corrupti. - include: + - Repudiandae enim molestiae. - Ut id iure. - - Est quod. - - Amet maiores repellendus eos. + include: + - Dolor sunt maiores. + - Asperiores omnis ducimus ad et mollitia. responses: "200": description: OK response. @@ -85,78 +96,41 @@ paths: $ref: '#/components/schemas/TestResults' example: collections: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 - results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - duration: 6968490088250328124 - fail_count: 3063074147820472067 - pass_count: 6067631605511723254 + duration: 1234 + fail_count: 1 + pass_count: 12 /tester/smoke: post: tags: - front summary: test_smoke front - description: Endpoint for running API Integration Tests for the Weather System + description: Endpoint for running API Integration Tests' Smoke Tests ONLY for the Weather System operationId: front#test_smoke responses: "200": @@ -167,72 +141,35 @@ paths: $ref: '#/components/schemas/TestResults' example: collections: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 - results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - duration: 9154617995926910546 - fail_count: 8279783259458611454 - pass_count: 3830585010251827564 + duration: 1234 + fail_count: 1 + pass_count: 12 components: schemas: Error: @@ -257,14 +194,14 @@ components: temporary: type: boolean description: Is the error temporary? - example: false + example: true timeout: type: boolean description: Is the error a timeout? - example: true + example: false description: IP address is not in the US example: - fault: true + fault: false id: 123abc message: parameter 'p' must be an integer name: bad_request @@ -325,6 +262,12 @@ components: summary: Clear temperature: 70 temperatureUnit: F + - endTime: "2020-01-01T00:00:00Z" + name: Morning + startTime: "2020-01-01T00:00:00Z" + summary: Clear + temperature: 70 + temperatureUnit: F required: - location - periods @@ -412,49 +355,49 @@ components: type: array items: type: string - example: Accusamus pariatur. + example: Cupiditate voluptas quod minima. description: Tests to exclude example: - - Ad sit in. - - Id et doloribus pariatur et. - - Exercitationem tempore. + - Vitae ut. + - Non officiis asperiores rem. include: type: array items: type: string - example: Exercitationem praesentium et. + example: Sed officia cum. description: Tests to run example: - - Aut sed mollitia. - - Numquam recusandae omnis occaecati sint praesentium est. + - Temporibus ex quo nihil rem. + - Et et itaque. example: exclude: - - Modi omnis sed. - - Id consequatur alias vitae voluptas quia. + - Architecto minima molestiae ad unde. + - Porro possimus iste eius minus nesciunt. + - Dolores ducimus. include: - - Doloremque et. - - Officia voluptates. + - Architecto aperiam odit. + - Iste eveniet. TestCollection: type: object properties: duration: type: integer - description: Duration of the tests in ns - example: 2079009122591064687 + description: Duration of the tests in ms + example: 1234 format: int64 fail_count: type: integer description: Number of tests that failed - example: 295202760764443778 + example: 1 format: int64 name: type: string description: Name of the test collection - example: Consequatur omnis ea. + example: Locator Tests pass_count: type: integer description: Number of tests that passed - example: 6357848907083386262 + example: 12 format: int64 results: type: array @@ -462,32 +405,43 @@ components: $ref: '#/components/schemas/TestResult' description: Test results example: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true description: Collection of test results for grouping by service example: - duration: 1981842416553121767 - fail_count: 8707465760791589491 - name: Inventore quae aspernatur quia. - pass_count: 936953043246880977 + duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP + passed: true + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true required: - name - - results - duration - pass_count - fail_count @@ -496,26 +450,26 @@ components: properties: duration: type: integer - description: Duration of the test in ns - example: 7518210316316224812 + description: Duration of the test in ms + example: 1234 format: int64 error: type: string description: Error message if the test failed - example: Dolor velit voluptates esse nesciunt eos et. + example: 'error getting location for valid ip: %v' name: type: string description: Name of the test - example: Non voluptas ex itaque rerum totam possimus. + example: TestValidIP passed: type: boolean description: Status of the test example: true description: Test result for a single test example: - duration: 2636828426958641278 - error: Sint accusantium est quisquam vitae modi est. - name: Voluptatem sit consectetur perferendis corrupti ipsam non. + duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true required: - name @@ -530,173 +484,104 @@ components: $ref: '#/components/schemas/TestCollection' description: Test collections example: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 - results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true duration: type: integer - description: Duration of the tests in ns - example: 6542909308659190311 + description: Duration of the tests in ms + example: 1234 format: int64 fail_count: type: integer description: Number of tests that failed - example: 5090292743939825689 + example: 1 format: int64 pass_count: type: integer description: Number of tests that passed - example: 4885942239601822760 + example: 12 format: int64 example: collections: - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 9054733701520478298 - fail_count: 7502424151970560367 - name: Id necessitatibus consequatur a laudantium quia qui. - pass_count: 8417812319446678629 + - duration: 1234 + fail_count: 1 + name: Locator Tests + pass_count: 12 results: - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. - passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - - duration: 859505013544304124 - error: Consectetur eos nihil accusamus reiciendis eligendi. - name: Dolorem nam quisquam laudantium incidunt ipsa. + - duration: 1234 + error: 'error getting location for valid ip: %v' + name: TestValidIP passed: true - duration: 6479921303740404391 - fail_count: 6775673673163648586 - pass_count: 921268878604032922 + duration: 1234 + fail_count: 1 + pass_count: 12 required: - collections - duration diff --git a/example/weather/services/tester/README.md b/example/weather/services/tester/README.md index c0f69fd7..daf6dea7 100644 --- a/example/weather/services/tester/README.md +++ b/example/weather/services/tester/README.md @@ -1,36 +1,76 @@ # Tester -The Tester service is a part of the weather application that is responsible for running various tests to ensure the functionality and reliability of the application. It is located in the example/weather/services/tester directory. -The service includes a set of predefined tests that are designed to validate different aspects of the application, such as the ability to locate IP addresses and forecast weather conditions. These tests are organized into three categories: smoke tests, forecaster tests, and locator tests. +The Tester service is a part of the weather application that is responsible for running various +tests to ensure the functionality and reliability of the application. It is located in the +example/weather/services/tester directory. + +The service includes a set of predefined tests that are designed to validate different aspects +of the application, such as the ability to locate IP addresses and forecast weather conditions. +These tests are organized into three categories: smoke tests, forecaster tests, and locator +tests. Port: `8090` ## Tester gRPC API Design -The Tester service exposes a gRPC API that allows other services (such as the externally facing `front` service) to run tests, or it be called directly. + +The Tester service exposes a gRPC API that allows other services (such as the externally facing +`front` service) to run tests, or for it to be called directly. ### TestResults return object -`TestResults`: This is the main return object for all test methods in the `tester` service and it represents the results of the system integration tests. It has four fields: `Collections` (an array of `TestCollection`), `Duration` (the total duration of all the tests in milliseconds), `PassCount` (the total number of tests that passed), and `FailCount` (the total number of tests that failed). -`TestCollection`: This type represents a collection of test results, typically grouped by service. It has five fields: `Name` (the name of the test collection), `Results` (an array of `TestResult`), `Duration` (the total duration of the tests in the `Collection` in milliseconds), `PassCount` (the number of tests that passed), and `FailCount` (the number of tests that failed). +`TestResults`: This is the main return object for all test methods in the `tester` service and +it represents the results of the system integration tests. It has four fields: `Collections` +(an array of `TestCollection`), `Duration` (the total duration of all the tests in milliseconds), +`PassCount` (the total number of tests that passed), and `FailCount` (the total number of tests +that failed). -`TestResult`: This type represents the result of a single test. It has four fields: `Name` (the name of the test), `Passed` (a boolean indicating whether the test passed), `Error` (an error message if the test failed), and `Duration` (the duration of the test in milliseconds). +`TestCollection`: This type represents a collection of test results, typically grouped by service. +It has five fields: `Name` (the name of the test collection), `Results` (an array of `TestResult`), +`Duration` (the total duration of the tests in the `Collection` in milliseconds), `PassCount` (the +number of tests that passed), and `FailCount` (the number of tests that failed). + +`TestResult`: This type represents the result of a single test. It has four fields: `Name` (the name +of the test), `Passed` (a boolean indicating whether the test passed), `Error` (an error message if +the test failed), and `Duration` (the duration of the test in milliseconds). ### TestSmoke method -`TestSmoke` takes no inputs and returns `TestResults``. It will run just the tests defined as smoke tests in `services/tester/func_map.go`. -`Smoke Tests` are a subset of all tests that are designed to provide a basic level of confidence that the application is functioning properly. +`TestSmoke` takes no inputs and returns `TestResults`. It will run just the tests defined as smoke +tests in `services/tester/func_map.go`. + +`Smoke Tests` are a subset of all tests that are designed to provide a basic level of confidence +that the application is functioning properly. ### TestAll method -`TestAll` takes a `TesterPayload` for optional filtering of tests and returns TestResults. It will run all tests defined in `services/tester/func_map.go`. -`TestPayload`: This type represents a payload that can be passed to the `TestAll` method to filter the tests that are run. It has two fields: `Include` (an array of strings that represent the names of tests to include) and `Exclude` (an array of strings that represent the names of tests to exclude). +`TestAll` takes a `TesterPayload` for optional filtering of tests and returns TestResults. It will +run all tests defined in `services/tester/func_map.go`. + +`TestPayload`: This type represents a payload that can be passed to the `TestAll` method to filter +the tests that are run. It has two fields: `Include` (an array of strings that represent the names +of tests to include) and `Exclude` (an array of strings that represent the names of tests to +exclude). + +`Include` and `Exclude` are mutually exclusive and cannot be used together. If that is done then +the `TestAll` method will return a `400 Bad Request` error. ### TestForecaster & TestLocator methods + These methods run all tests defined for those services as found in `services/tester/func_map.go`. ## Tester exposed via Front -The `front` service exposes the `TestAll` and `TestSmoke` methods via gRPC. This allows the `front` service to tests in the application and return the results to the caller. -This is useful when your gRPC services are not exposed publicly but your application still needs to be tested. In this case, the `front` service can be exposed publicly (with appropriate authentication required) and used to run tests on the application. This allows you to run tests on your application without exposing your gRPC services publicly. +The `front` service exposes the `TestAll` and `TestSmoke` methods via gRPC. This allows the `front` +service to tests in the application and return the results to the caller. + +This is useful when your gRPC services are not exposed publicly but your application still needs to +be tested. In this case, the `front` service can be exposed publicly (with appropriate +authentication required) and used to run tests on the application. This allows you to run tests on +your application without exposing your gRPC services publicly. -An example of usage like this is to use the `front` service to run tests on the application from a CI/CD pipeline. A bash script can be written that calls the `front` service to run tests on the application and then exits with an error code if any tests fail. This script can then be called from a GitHub Actions workflow to run tests on the application after each commit, and even parse the results using a cli like `jq` to provide more detailed information about the test results in a comment to a PR. \ No newline at end of file +An example of usage like this is to use the `front` service to run tests on the application from a +CI/CD pipeline. A bash script can be written that calls the `front` service to run tests on the +application and then exits with an error code if any tests fail. This script can then be called +from a GitHub Actions workflow to run tests on the application after each commit, and even parse +the results using a cli like `jq` to provide more detailed information about the test results in a +comment to a PR. \ No newline at end of file diff --git a/example/weather/services/tester/design/design.go b/example/weather/services/tester/design/design.go index 469c46a3..0773a262 100644 --- a/example/weather/services/tester/design/design.go +++ b/example/weather/services/tester/design/design.go @@ -58,36 +58,60 @@ var _ = Service("tester", func() { var TestResult = Type("TestResult", func() { Description("Test result for a single test") - Field(1, "Name", String, "Name of the test") + Field(1, "Name", String, "Name of the test", func() { + Example("TestName") + }) Field(2, "Passed", Boolean, "Status of the test", func() { Example(true) }) - Field(3, "Error", String, "Error message if the test failed") - Field(4, "Duration", Int64, "Duration of the test in ms") + Field(3, "Error", String, "Error message if the test failed", func() { + Example("Error message") + }) + Field(4, "Duration", Int64, "Duration of the test in ms", func() { + Example(100) + }) Required("Name", "Passed", "Duration") }) var TestCollection = Type("TestCollection", func() { Description("Collection of test results for grouping by service") - Field(1, "Name", String, "Name of the test collection") + Field(1, "Name", String, "Name of the test collection", func() { + Example("TestCollectionName") + }) Field(2, "Results", ArrayOf(TestResult), "Test results") - Field(3, "Duration", Int64, "Duration of the tests in ms") - Field(4, "PassCount", Int, "Number of tests that passed") - Field(5, "FailCount", Int, "Number of tests that failed") - Required("Name", "Results", "Duration", "PassCount", "FailCount") + Field(3, "Duration", Int64, "Duration of the tests in ms", func() { + Example(100) + }) + Field(4, "PassCount", Int, "Number of tests that passed", func() { + Example(10) + }) + Field(5, "FailCount", Int, "Number of tests that failed", func() { + Example(1) + }) + Required("Name", "Duration", "PassCount", "FailCount") }) var TestResults = Type("TestResults", func() { Description("Test results for the iam system integration tests") Field(1, "Collections", ArrayOf(TestCollection), "Test collections") - Field(2, "Duration", Int64, "Duration of the tests in ms") - Field(3, "PassCount", Int, "Number of tests that passed") - Field(4, "FailCount", Int, "Number of tests that failed") + Field(2, "Duration", Int64, "Duration of the tests in ms", func() { + Example(100) + }) + Field(3, "PassCount", Int, "Number of tests that passed", func() { + Example(10) + }) + Field(4, "FailCount", Int, "Number of tests that failed", func() { + Example(1) + }) Required("Collections", "Duration", "PassCount", "FailCount") }) var SystemTestPayload = Type("TesterPayload", func() { Description("Payload for the tester service") - Field(1, "Include", ArrayOf(String), "Tests to run") - Field(2, "Exclude", ArrayOf(String), "Tests to exclude") + Field(1, "Include", ArrayOf(String), "Tests to run", func() { + Example([]string{"TestNameToInclude"}) + }) + Field(2, "Exclude", ArrayOf(String), "Tests to exclude", func() { + Example([]string{"TestNameToExclude"}) + }) }) diff --git a/example/weather/services/tester/func_map.go b/example/weather/services/tester/func_map.go index 1049b56c..06ee0804 100644 --- a/example/weather/services/tester/func_map.go +++ b/example/weather/services/tester/func_map.go @@ -1,20 +1,35 @@ package tester +// The func_map.go file contains the maps that map test names to the actual test functions. Test +// functions are defined in the integration.go files for each service. The maps are used in the +// tester service to run the tests. Names are used for filtering which tests to run when TestAll +// is called. +// +// The smokeTestMap is a map that associates smoke test names with their corresponding test +// functions. +// +// Similarly, forecasterTestMap and locatorTestMap are maps that associate forecaster and locator +// test names with their corresponding test functions. +// +// The smokeTestMap is used exclusively when TestSmoke is called in the tester service. It will +// contain a subset of the tests defined in the service-specific test maps (such as those for +// locator and forecaster). + import "context" var smokeTestMap = make(map[string]func(context.Context, *TestCollection)) func (svc *Service) smokeTestMapInit(ctx context.Context) { - smokeTestMap["TestValidLatLong"] = svc.TestForecasterValidLatLong + smokeTestMap["TestForecasterValidLatLong"] = svc.TestForecasterValidLatLong smokeTestMap["TestLocatorValidIP"] = svc.TestLocatorValidIP } var forecasterTestMap = make(map[string]func(context.Context, *TestCollection)) func (svc *Service) forecasterTestMapInit(ctx context.Context) { - forecasterTestMap["TestValidLatLong"] = svc.TestForecasterValidLatLong - forecasterTestMap["TestInvalidLat"] = svc.TestForecasterInvalidLat - forecasterTestMap["TestInvalidLong"] = svc.TestForecasterInvalidLong + forecasterTestMap["TestForecasterValidLatLong"] = svc.TestForecasterValidLatLong + forecasterTestMap["TestForecasterInvalidLat"] = svc.TestForecasterInvalidLat + forecasterTestMap["TestForecasterInvalidLong"] = svc.TestForecasterInvalidLong } var locatorTestMap = make(map[string]func(context.Context, *TestCollection)) diff --git a/example/weather/services/tester/gen/grpc/cli/tester_service_api/cli.go b/example/weather/services/tester/gen/grpc/cli/tester_service_api/cli.go index 1c27bb8b..4bad40b3 100644 --- a/example/weather/services/tester/gen/grpc/cli/tester_service_api/cli.go +++ b/example/weather/services/tester/gen/grpc/cli/tester_service_api/cli.go @@ -30,13 +30,10 @@ func UsageCommands() string { func UsageExamples() string { return os.Args[0] + ` tester test-all --message '{ "Exclude": [ - "Aut ullam iure iure in fugiat.", - "Asperiores neque delectus non officiis hic." + "TestNameToExclude" ], "Include": [ - "Animi accusamus facilis sed exercitationem unde saepe.", - "Error omnis quam ducimus eaque similique.", - "Laboriosam dicta commodi beatae dolorem." + "TestNameToInclude" ] }'` + "\n" + "" @@ -181,13 +178,10 @@ Runs all tests in the iam system Example: %[1]s tester test-all --message '{ "Exclude": [ - "Aut ullam iure iure in fugiat.", - "Asperiores neque delectus non officiis hic." + "TestNameToExclude" ], "Include": [ - "Animi accusamus facilis sed exercitationem unde saepe.", - "Error omnis quam ducimus eaque similique.", - "Laboriosam dicta commodi beatae dolorem." + "TestNameToInclude" ] }' `, os.Args[0]) diff --git a/example/weather/services/tester/gen/grpc/tester/client/cli.go b/example/weather/services/tester/gen/grpc/tester/client/cli.go index a6a65931..639528d0 100644 --- a/example/weather/services/tester/gen/grpc/tester/client/cli.go +++ b/example/weather/services/tester/gen/grpc/tester/client/cli.go @@ -25,7 +25,7 @@ func BuildTestAllPayload(testerTestAllMessage string) (*tester.TesterPayload, er if testerTestAllMessage != "" { err = json.Unmarshal([]byte(testerTestAllMessage), &message) if err != nil { - return nil, fmt.Errorf("invalid JSON for message, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"Exclude\": [\n \"Aut ullam iure iure in fugiat.\",\n \"Asperiores neque delectus non officiis hic.\"\n ],\n \"Include\": [\n \"Animi accusamus facilis sed exercitationem unde saepe.\",\n \"Error omnis quam ducimus eaque similique.\",\n \"Laboriosam dicta commodi beatae dolorem.\"\n ]\n }'") + return nil, fmt.Errorf("invalid JSON for message, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"Exclude\": [\n \"TestNameToExclude\"\n ],\n \"Include\": [\n \"TestNameToInclude\"\n ]\n }'") } } } diff --git a/example/weather/services/tester/gen/grpc/tester/client/types.go b/example/weather/services/tester/gen/grpc/tester/client/types.go index e3039953..4b409045 100644 --- a/example/weather/services/tester/gen/grpc/tester/client/types.go +++ b/example/weather/services/tester/gen/grpc/tester/client/types.go @@ -191,21 +191,6 @@ func ValidateTestAllResponse(message *testerpb.TestAllResponse) (err error) { if message.Collections == nil { err = goa.MergeErrors(err, goa.MissingFieldError("Collections", "message")) } - for _, e := range message.Collections { - if e != nil { - if err2 := ValidateTestCollection(e); err2 != nil { - err = goa.MergeErrors(err, err2) - } - } - } - return -} - -// ValidateTestCollection runs the validations defined on TestCollection. -func ValidateTestCollection(elem *testerpb.TestCollection) (err error) { - if elem.Results == nil { - err = goa.MergeErrors(err, goa.MissingFieldError("Results", "elem")) - } return } @@ -214,13 +199,6 @@ func ValidateTestSmokeResponse(message *testerpb.TestSmokeResponse) (err error) if message.Collections == nil { err = goa.MergeErrors(err, goa.MissingFieldError("Collections", "message")) } - for _, e := range message.Collections { - if e != nil { - if err2 := ValidateTestCollection(e); err2 != nil { - err = goa.MergeErrors(err, err2) - } - } - } return } @@ -230,13 +208,6 @@ func ValidateTestForecasterResponse(message *testerpb.TestForecasterResponse) (e if message.Collections == nil { err = goa.MergeErrors(err, goa.MissingFieldError("Collections", "message")) } - for _, e := range message.Collections { - if e != nil { - if err2 := ValidateTestCollection(e); err2 != nil { - err = goa.MergeErrors(err, err2) - } - } - } return } @@ -246,12 +217,5 @@ func ValidateTestLocatorResponse(message *testerpb.TestLocatorResponse) (err err if message.Collections == nil { err = goa.MergeErrors(err, goa.MissingFieldError("Collections", "message")) } - for _, e := range message.Collections { - if e != nil { - if err2 := ValidateTestCollection(e); err2 != nil { - err = goa.MergeErrors(err, err2) - } - } - } return } diff --git a/example/weather/services/tester/run_tests.go b/example/weather/services/tester/run_tests.go index 85d0f194..8e0159dc 100644 --- a/example/weather/services/tester/run_tests.go +++ b/example/weather/services/tester/run_tests.go @@ -14,7 +14,7 @@ import ( "golang.org/x/exp/slices" ) -// Ends a test by calculating duration and appending teh results to the test collection +// Ends a test by calculating duration and appending the results to the test collection func endTest(tr *gentester.TestResult, start time.Time, tc *TestCollection, results []*gentester.TestResult) { elapsed := time.Since(start).Milliseconds() tr.Duration = elapsed @@ -43,7 +43,7 @@ func recoverFromTestPanic(ctx context.Context, testName string, testCollection * } // Runs the tests from the testmap and handles filtering/exclusion of tests -func (svc *Service) runTests(ctx context.Context, p *gentester.TesterPayload, testCollection *TestCollection, testMap map[string]func(context.Context, *TestCollection)) (res *gentester.TestResults, err error) { +func (svc *Service) runTests(ctx context.Context, p *gentester.TesterPayload, testCollection *TestCollection, testMap map[string]func(context.Context, *TestCollection)) (*gentester.TestResults, error) { retval := gentester.TestResults{} testsToRun := make(map[string]func(context.Context, *TestCollection)) @@ -59,7 +59,7 @@ func (svc *Service) runTests(ctx context.Context, p *gentester.TesterPayload, te return nil, gentester.MakeIncludeExcludeBoth(errors.New("cannot have both include and exclude lists")) } for _, test := range p.Include { - if testFunc, exists := testMap[test]; exists { + if testFunc, ok := testMap[test]; ok { testsToRun[test] = testFunc } else { // QUESTION: Do we want to error the test execution if a test is not found in the test map? @@ -88,23 +88,17 @@ func (svc *Service) runTests(ctx context.Context, p *gentester.TesterPayload, te for n, test := range testsToRun { wg.Add(1) go func(f func(context.Context, *TestCollection), testName string) { - defer recoverFromTestPanic(ctx, testName, testCollection) defer wg.Done() + defer recoverFromTestPanic(ctx, testName, testCollection) log.Infof(ctx, "RUNNING TEST [%v]", testName) f(ctx, testCollection) }(test, n) } wg.Wait() - // If there was a Panic in the test, sometimes it falls through to and checks results from the test collection - // before it finishes the deferred recoverFromTestPanic, making it look like the panicked test was not handled - // or run. This sleep is to give the recoverFromTestPanic function time to finish before we check the results. - time.Sleep(250 * time.Millisecond) - for _, res := range testCollection.Results { if !res.Passed { - errorMessage := *res.Error - log.Infof(ctx, "[Failed Test] Collection: [%v], Test [%v] failed with message [%s] and a duration of [%v]", testCollection.Name, res.Name, errorMessage, res.Duration) + log.Infof(ctx, "[Failed Test] Collection: [%v], Test [%v] failed with message [%s] and a duration of [%v]", testCollection.Name, res.Name, *res.Error, res.Duration) } } diff --git a/example/weather/services/tester/testing.go b/example/weather/services/tester/testing.go index 3d9d6486..0137ed62 100644 --- a/example/weather/services/tester/testing.go +++ b/example/weather/services/tester/testing.go @@ -15,6 +15,7 @@ type ( } ) +// New instantiates a new tester service. func New(lc locator.Client, fc forecaster.Client) *Service { return &Service{ lc: lc, diff --git a/go.work.sum b/go.work.sum index ac60d532..cdc0f096 100644 --- a/go.work.sum +++ b/go.work.sum @@ -358,14 +358,17 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= +github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -378,12 +381,14 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/dimfeld/httptreemux/v5 v5.5.0 h1:p8jkiMrCuZ0CmhwYLcbNbl7DDo21fozhKHQ2PccwOFQ= github.com/dimfeld/httptreemux/v5 v5.5.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -392,6 +397,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= +github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -419,6 +425,7 @@ github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -503,6 +510,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= @@ -524,6 +532,7 @@ github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhg github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/smartystreets/assertions v1.2.1 h1:bKNHfEv7tSIjZ8JbKaFjzFINljxG4lzZvmHUnElzOIg= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -535,6 +544,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -557,6 +567,7 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0 golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -730,6 +741,7 @@ golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=