Skip to content

Commit

Permalink
feat: test models + list tests endpoint (#2681)
Browse files Browse the repository at this point in the history
* add test, run, and trigger objects

* feat: move test and run structs into the test package

* list tests

* add old format attributes again

* fix mapping

* compatibility mode

* fix server prefix integration test

* force server unit tests to run

* fix tracetest test

* trigger CI

* Apply suggestions from code review

Co-authored-by: Sebastian Choren <[email protected]>

* fix build

* version test specs

* update test names

* use sqlutils

* dont specify branch target in pull_request

* fix list test

---------

Co-authored-by: Sebastian Choren <[email protected]>
  • Loading branch information
mathnogueira and schoren committed Jul 3, 2023
1 parent 405eb0d commit a4d4a73
Show file tree
Hide file tree
Showing 35 changed files with 1,589 additions and 172 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]

env:
VERSION: ${{ github.sha }}
Expand Down Expand Up @@ -88,7 +87,7 @@ jobs:
cache: true
cache-dependency-path: go.work
- name: Run unit tests
run: cd server; make test
run: cd server; make test -B

unit-test-web:
name: WebUI unit tests
Expand Down
3 changes: 3 additions & 0 deletions api/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ components:
createdAt:
type: string
format: date-time
# TODO: remove serviceUnderTest after test migration
serviceUnderTest:
$ref: "./triggers.yaml#/components/schemas/Trigger"
trigger:
$ref: "./triggers.yaml#/components/schemas/Trigger"
specs:
type: array
items:
Expand Down
8 changes: 8 additions & 0 deletions api/triggers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ components:
Trigger:
type: object
properties:
type:
type: string
enum: ["http", "grpc", "traceid"]
# TODO: remove after test migration
triggerType:
type: string
enum: ["http", "grpc", "traceid"]
Expand All @@ -17,9 +21,13 @@ components:
TriggerResult:
type: object
properties:
# TODO: remove after test migration
triggerType:
type: string
enum: ["http", "grpc", "traceid"]
type:
type: string
enum: ["http", "grpc", "traceid"]
triggerResult:
type: object
properties:
Expand Down
50 changes: 32 additions & 18 deletions server/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package app

import (
"context"
"database/sql"
"errors"
"fmt"
"log"
Expand Down Expand Up @@ -31,6 +30,7 @@ import (
"github.com/kubeshop/tracetest/server/provisioning"
"github.com/kubeshop/tracetest/server/resourcemanager"
"github.com/kubeshop/tracetest/server/subscription"
"github.com/kubeshop/tracetest/server/test"
"github.com/kubeshop/tracetest/server/testdb"
"github.com/kubeshop/tracetest/server/tracedb"
"github.com/kubeshop/tracetest/server/traces"
Expand Down Expand Up @@ -194,10 +194,12 @@ func (app *App) Start(opts ...appOption) error {

triggerRegistry := getTriggerRegistry(tracer, applicationTracer)

demoRepo := demo.NewRepository(db)
pollingProfileRepo := pollingprofile.NewRepository(db)
dataStoreRepo := datastore.NewRepository(db)
environmentRepo := environment.NewRepository(db)
linterRepo := analyzer.NewRepository(db)
testRepo := test.NewRepository(db)

eventEmitter := executor.NewEventEmitter(testDB, subscriptionManager)
registerOtlpServer(app, testDB, eventEmitter, dataStoreRepo)
Expand Down Expand Up @@ -258,17 +260,13 @@ func (app *App) Start(opts ...appOption) error {
Subrouter()

registerTransactionResource(transactionsRepository, apiRouter, provisioner, tracer)

registerConfigResource(configRepo, apiRouter, db, provisioner, tracer)

registerPollingProfilesResource(pollingProfileRepo, apiRouter, db, provisioner, tracer)
registerEnvironmentResource(environmentRepo, apiRouter, db, provisioner, tracer)

demoRepo := demo.NewRepository(db)
registerDemosResource(demoRepo, apiRouter, db, provisioner, tracer)

registerDataStoreResource(dataStoreRepo, apiRouter, db, provisioner, tracer)
registerAnalyzerResource(linterRepo, apiRouter, db, provisioner, tracer)
registerConfigResource(configRepo, apiRouter, provisioner, tracer)
registerPollingProfilesResource(pollingProfileRepo, apiRouter, provisioner, tracer)
registerEnvironmentResource(environmentRepo, apiRouter, provisioner, tracer)
registerDemosResource(demoRepo, apiRouter, provisioner, tracer)
registerDataStoreResource(dataStoreRepo, apiRouter, provisioner, tracer)
registerAnalyzer(linterRepo, apiRouter, provisioner, tracer)
registerTestResource(testRepo, apiRouter, provisioner, tracer)

isTracetestDev := os.Getenv("TRACETEST_DEV") != ""
registerSPAHandler(router, app.cfg, configFromDB.IsAnalyticsEnabled(), serverID, isTracetestDev)
Expand Down Expand Up @@ -356,7 +354,7 @@ func registerOtlpServer(app *App, testDB model.Repository, eventEmitter executor
})
}

func registerAnalyzerResource(linterRepo *analyzer.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerAnalyzer(linterRepo *analyzer.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[analyzer.Linter](
analyzer.ResourceName,
analyzer.ResourceNamePlural,
Expand All @@ -380,7 +378,7 @@ func registerTransactionResource(repo *transaction.Repository, router *mux.Route
provisioner.AddResourceProvisioner(manager)
}

func registerConfigResource(configRepo *config.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerConfigResource(configRepo *config.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[config.Config](
config.ResourceName,
config.ResourceNamePlural,
Expand All @@ -392,7 +390,7 @@ func registerConfigResource(configRepo *config.Repository, router *mux.Router, d
provisioner.AddResourceProvisioner(manager)
}

func registerPollingProfilesResource(repository *pollingprofile.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerPollingProfilesResource(repository *pollingprofile.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[pollingprofile.PollingProfile](
pollingprofile.ResourceName,
pollingprofile.ResourceNamePlural,
Expand All @@ -404,7 +402,7 @@ func registerPollingProfilesResource(repository *pollingprofile.Repository, rout
provisioner.AddResourceProvisioner(manager)
}

func registerEnvironmentResource(repository *environment.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerEnvironmentResource(repository *environment.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[environment.Environment](
environment.ResourceName,
environment.ResourceNamePlural,
Expand All @@ -415,7 +413,7 @@ func registerEnvironmentResource(repository *environment.Repository, router *mux
provisioner.AddResourceProvisioner(manager)
}

func registerDemosResource(repository *demo.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerDemosResource(repository *demo.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[demo.Demo](
demo.ResourceName,
demo.ResourceNamePlural,
Expand All @@ -426,7 +424,7 @@ func registerDemosResource(repository *demo.Repository, router *mux.Router, db *
provisioner.AddResourceProvisioner(manager)
}

func registerDataStoreResource(repository *datastore.Repository, router *mux.Router, db *sql.DB, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
func registerDataStoreResource(repository *datastore.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
manager := resourcemanager.New[datastore.DataStore](
datastore.ResourceName,
datastore.ResourceNamePlural,
Expand All @@ -437,6 +435,22 @@ func registerDataStoreResource(repository *datastore.Repository, router *mux.Rou
provisioner.AddResourceProvisioner(manager)
}

func registerTestResource(repository test.Repository, router *mux.Router, provisioner *provisioning.Provisioner, tracer trace.Tracer) {
operations := []resourcemanager.Operation{
resourcemanager.OperationList,
}

manager := resourcemanager.New[test.Test](
test.ResourceName,
test.ResourceNamePlural,
repository,
resourcemanager.WithOperations(operations...),
resourcemanager.WithTracer(tracer),
)
manager.RegisterRoutes(router)
provisioner.AddResourceProvisioner(manager)
}

func getTriggerRegistry(tracer, appTracer trace.Tracer) *trigger.Registry {
triggerReg := trigger.NewRegsitry(tracer, appTracer)
triggerReg.Add(trigger.HTTP())
Expand Down
4 changes: 0 additions & 4 deletions server/config/demo/main_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
<<<<<<<< HEAD:server/config/demo/main_test.go
package demo_test
========
package transactions_test
>>>>>>>> 7fb86839 (fix: move transactions to it's own module (#2664)):server/transactions/main_test.go

import (
"os"
Expand Down
1 change: 0 additions & 1 deletion server/http/custom_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ func (c *customController) Routes() openapi.Routes {

routes[c.getRouteIndex("GetTestRuns")].HandlerFunc = c.GetTestRuns

routes[c.getRouteIndex("GetTests")].HandlerFunc = paginatedEndpoint[openapi.Test](c.service.GetTests, c.errorHandler)
routes[c.getRouteIndex("GetResources")].HandlerFunc = paginatedEndpoint[openapi.Resource](c.service.GetResources, c.errorHandler)

for index, route := range routes {
Expand Down
6 changes: 3 additions & 3 deletions server/integration/ensure_server_prefix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"github.com/goccy/go-yaml"
"github.com/kubeshop/tracetest/server/app"
"github.com/kubeshop/tracetest/server/datastore"
"github.com/kubeshop/tracetest/server/openapi"
"github.com/kubeshop/tracetest/server/resourcemanager"
"github.com/kubeshop/tracetest/server/test"
"github.com/kubeshop/tracetest/server/testmock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -55,7 +55,7 @@ func TestServerPrefix(t *testing.T) {
assert.GreaterOrEqual(t, dataStores.Count, 1)
}

func getTests(t *testing.T, endpoint string) []openapi.Test {
func getTests(t *testing.T, endpoint string) resourcemanager.ResourceList[test.Test] {
url := fmt.Sprintf("%s/api/tests", endpoint)
resp, err := http.Get(url)
require.NoError(t, err)
Expand All @@ -64,7 +64,7 @@ func getTests(t *testing.T, endpoint string) []openapi.Test {
bodyJsonBytes, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)

var tests []openapi.Test
var tests resourcemanager.ResourceList[test.Test]
err = json.Unmarshal(bodyJsonBytes, &tests)
require.NoError(t, err)

Expand Down
4 changes: 2 additions & 2 deletions server/openapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ type ApiApiRouter interface {
GetTestSpecs(http.ResponseWriter, *http.Request)
GetTestVersion(http.ResponseWriter, *http.Request)
GetTestVersionDefinitionFile(http.ResponseWriter, *http.Request)
GetTests(http.ResponseWriter, *http.Request)
GetTransactionRun(http.ResponseWriter, *http.Request)
GetTransactionRuns(http.ResponseWriter, *http.Request)
GetTransactionVersion(http.ResponseWriter, *http.Request)
Expand Down Expand Up @@ -71,6 +70,7 @@ type ResourceApiApiRouter interface {
GetEnvironment(http.ResponseWriter, *http.Request)
GetLinter(http.ResponseWriter, *http.Request)
GetPollingProfile(http.ResponseWriter, *http.Request)
GetTests(http.ResponseWriter, *http.Request)
GetTransaction(http.ResponseWriter, *http.Request)
GetTransactions(http.ResponseWriter, *http.Request)
ListConfiguration(http.ResponseWriter, *http.Request)
Expand Down Expand Up @@ -111,7 +111,6 @@ type ApiApiServicer interface {
GetTestSpecs(context.Context, string) (ImplResponse, error)
GetTestVersion(context.Context, string, int32) (ImplResponse, error)
GetTestVersionDefinitionFile(context.Context, string, int32) (ImplResponse, error)
GetTests(context.Context, int32, int32, string, string, string) (ImplResponse, error)
GetTransactionRun(context.Context, string, int32) (ImplResponse, error)
GetTransactionRuns(context.Context, string, int32, int32) (ImplResponse, error)
GetTransactionVersion(context.Context, string, int32) (ImplResponse, error)
Expand Down Expand Up @@ -147,6 +146,7 @@ type ResourceApiApiServicer interface {
GetEnvironment(context.Context, string) (ImplResponse, error)
GetLinter(context.Context, string) (ImplResponse, error)
GetPollingProfile(context.Context, string) (ImplResponse, error)
GetTests(context.Context, int32, int32, string, string, string) (ImplResponse, error)
GetTransaction(context.Context, string) (ImplResponse, error)
GetTransactions(context.Context, int32, int32, string, string, string) (ImplResponse, error)
ListConfiguration(context.Context, int32, int32, string, string) (ImplResponse, error)
Expand Down
33 changes: 0 additions & 33 deletions server/openapi/api_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,6 @@ func (c *ApiApiController) Routes() Routes {
"/api/tests/{testId}/version/{version}/definition.yaml",
c.GetTestVersionDefinitionFile,
},
{
"GetTests",
strings.ToUpper("Get"),
"/api/tests",
c.GetTests,
},
{
"GetTransactionRun",
strings.ToUpper("Get"),
Expand Down Expand Up @@ -652,33 +646,6 @@ func (c *ApiApiController) GetTestVersionDefinitionFile(w http.ResponseWriter, r

}

// GetTests - Get tests
func (c *ApiApiController) GetTests(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
takeParam, err := parseInt32Parameter(query.Get("take"), false)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
skipParam, err := parseInt32Parameter(query.Get("skip"), false)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
queryParam := query.Get("query")
sortByParam := query.Get("sortBy")
sortDirectionParam := query.Get("sortDirection")
result, err := c.service.GetTests(r.Context(), takeParam, skipParam, queryParam, sortByParam, sortDirectionParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)

}

// GetTransactionRun - Get a specific run from a particular transaction
func (c *ApiApiController) GetTransactionRun(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
Expand Down
33 changes: 33 additions & 0 deletions server/openapi/api_resource_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ func (c *ResourceApiApiController) Routes() Routes {
"/api/pollingprofiles/{pollingProfileId}",
c.GetPollingProfile,
},
{
"GetTests",
strings.ToUpper("Get"),
"/api/tests",
c.GetTests,
},
{
"GetTransaction",
strings.ToUpper("Get"),
Expand Down Expand Up @@ -505,6 +511,33 @@ func (c *ResourceApiApiController) GetPollingProfile(w http.ResponseWriter, r *h

}

// GetTests - Get tests
func (c *ResourceApiApiController) GetTests(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
takeParam, err := parseInt32Parameter(query.Get("take"), false)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
skipParam, err := parseInt32Parameter(query.Get("skip"), false)
if err != nil {
c.errorHandler(w, r, &ParsingError{Err: err}, nil)
return
}
queryParam := query.Get("query")
sortByParam := query.Get("sortBy")
sortDirectionParam := query.Get("sortDirection")
result, err := c.service.GetTests(r.Context(), takeParam, skipParam, queryParam, sortByParam, sortDirectionParam)
// If an error occurred, encode the error with the status code
if err != nil {
c.errorHandler(w, r, err, &result)
return
}
// If no error, encode the body and the result code
EncodeJSONResponse(result.Body, &result.Code, w)

}

// GetTransaction - get transaction
func (c *ResourceApiApiController) GetTransaction(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
Expand Down
17 changes: 17 additions & 0 deletions server/openapi/api_resource_api_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,23 @@ func (s *ResourceApiApiService) GetPollingProfile(ctx context.Context, pollingPr
return Response(http.StatusNotImplemented, nil), errors.New("GetPollingProfile method not implemented")
}

// GetTests - Get tests
func (s *ResourceApiApiService) GetTests(ctx context.Context, take int32, skip int32, query string, sortBy string, sortDirection string) (ImplResponse, error) {
// TODO - update GetTests with the required logic for this service method.
// Add api_resource_api_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation.

//TODO: Uncomment the next line to return response Response(200, TestResourceList{}) or use other options such as http.Ok ...
//return Response(200, TestResourceList{}), nil

//TODO: Uncomment the next line to return response Response(400, {}) or use other options such as http.Ok ...
//return Response(400, nil),nil

//TODO: Uncomment the next line to return response Response(500, {}) or use other options such as http.Ok ...
//return Response(500, nil),nil

return Response(http.StatusNotImplemented, nil), errors.New("GetTests method not implemented")
}

// GetTransaction - get transaction
func (s *ResourceApiApiService) GetTransaction(ctx context.Context, transactionId string) (ImplResponse, error) {
// TODO - update GetTransaction with the required logic for this service method.
Expand Down
5 changes: 5 additions & 0 deletions server/openapi/model_test_.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Test struct {

ServiceUnderTest Trigger `json:"serviceUnderTest,omitempty"`

Trigger Trigger `json:"trigger,omitempty"`

// specification of assertions that are going to be made
Specs []TestSpec `json:"specs,omitempty"`

Expand All @@ -41,6 +43,9 @@ func AssertTestRequired(obj Test) error {
if err := AssertTriggerRequired(obj.ServiceUnderTest); err != nil {
return err
}
if err := AssertTriggerRequired(obj.Trigger); err != nil {
return err
}
for _, el := range obj.Specs {
if err := AssertTestSpecRequired(el); err != nil {
return err
Expand Down
Loading

0 comments on commit a4d4a73

Please sign in to comment.