Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First stage of new tests which share logic with library tests #348

Merged
merged 2 commits into from
Feb 23, 2021
Merged

First stage of new tests which share logic with library tests #348

merged 2 commits into from
Feb 23, 2021

Conversation

mmulholla
Copy link
Contributor

This is part1 of replacing the existing api tests and is a work in progress. The idea is for the library test and api test to use the same code for generating valid devfiles which will exist in the api repo. The code is not complete yet but the current set of tests run. The library tests depend on this PR before they can be merged.

Things to do include, but are not limited to:

  • Expand tests to fully cover the schema.
  • Expand test README with more detail on how the tests work and how to update them.
  • Come up with a way to configure which schema to use.

For more information see: #347


// WriteAndVerify implements Saved.DevfileValidator interface.
// writes to disk and validates the specified devfile
func (devfileValidator DevfileValidator) WriteAndValidate(devfile *common.TestDevfile) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps function WriteAndValidate and writeDevfile can be under pkg test/v200/utils/common?
So you do not need to define the empty struct DevfileValidator to avoid import cycle

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method implementations are completely different comparing the api and library implementations so they do not belong in the common. This is the standard way of implementing an interface declared in a different package.

test/README.md Outdated Show resolved Hide resolved
}
}

err := testDevfile.Validator.WriteAndValidate(testDevfile)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing and had to back track a couple of times to follow it, we are calling an interface implementation for validator but the func takes its own entire struct?

I am not sure if this is a clean way to do it in Go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am all ears for a better way to do it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked briefly at the code but didn't easily find definitions for the various structs/interfaces used (i.e. where does Validator come from), but the way to do it would be to make TestDevfile implement the Validator interface:

type Validator interface {
  WriteAndValidate() error
}

type TestDevfile struct {
  myField string
  mySetting bool
}

func (t *TestDevfile) WriteAndValidate() error {
  t.myField = "write"
  if !t.mySetting {
    return errors.New("Bad setting")
  }
}

// Now `TestDevfile` can be used wherever a `DevfileValidator` is needed

Copy link
Member

@maysunfaisal maysunfaisal Feb 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In common/test_utils.go, you can update:

// DevfileValidator interface implemented by the parser and api tests for verifying generated devfiles
type DevfileValidator interface {
	WriteAndValidate(*TestDevfile, DevfileFollower) error
}

// Runs a test to create and verify a devfile based on the content of the specified TestContent
func (testDevfile *TestDevfile) RunTest(testContent TestContent, t *testing.T, follower DevfileFollower, validator DevfileValidator) {

...

err := validator.WriteAndValidate(testDevfile, follower)
	if err != nil {
		t.Fatalf(LogErrorMessage(fmt.Sprintf("ERROR verifying devfile :  %s : %v", testContent.FileName, err)))
	}

}

in api/test_utils.go, you can update:

// WriteAndValidate implements Saved.DevfileValidator interface.
// writes to disk and validates the specified devfile
func (devfileValidator DevfileValidator) WriteAndValidate(devfile *commonUtils.TestDevfile, follower commonUtils.DevfileFollower) error {
	err := writeDevfile(devfile)
	
	...
}


// RunTest : Runs a test to create and verify a devfile based on the content of the specified TestContent
func RunTest(testContent commonUtils.TestContent, t *testing.T) {

      ...

       testDevfile.RunTest(testContent, t, nil, validator)
}

That way you dont have to embed validator and follower in TestDevfile and its much easier to read and track

Copy link
Contributor Author

@mmulholla mmulholla Feb 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how your versions are not much uglier than mine. The follower is needed in the common code before the validator. Add the interface to an existing structure is better than a specific obviously named structure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understand this is a test, it is meant to exercise the library api's it is not meant to be the most efficient, some places it goes out of its way to pound the api . The common code informs the follower every time something is added to the devfile, which will end up as twice for each property added to schema, for example once to add an empty command and a second to update it with attributes. This is only needed for the parser. Once the entire devfile is created it needs to be written out and validated, which is different for the parser and the api hence the validator. This set up means the api side does not need and empty follower. This is. the pain of having common code.

test/v200/utils/api/test_utils.go Outdated Show resolved Hide resolved
test/v200/utils/api/test_utils.go Outdated Show resolved Hide resolved
test/v200/utils/api/test_utils.go Outdated Show resolved Hide resolved
test/v200/utils/common/command_test_utils.go Outdated Show resolved Hide resolved
test/v200/utils/api/test_utils.go Show resolved Hide resolved
test/v200/utils/api/test_utils.go Outdated Show resolved Hide resolved
test/v200/apiTest/api_test.go Outdated Show resolved Hide resolved
test/v200/apiTest/api_test.go Show resolved Hide resolved
// Convert the yaml file to json
devfileDataAsJSON, err := yaml.YAMLToJSON(devfileData)
if err != nil {
common.LogErrorMessage(fmt.Sprintf(" FAIL : %s : schema : failed to convert to json : %v", devfile, err))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplify the message

Suggested change
common.LogErrorMessage(fmt.Sprintf(" FAIL : %s : schema : failed to convert to json : %v", devfile, err))
common.LogErrorMessage(fmt.Sprintf(" FAIL : schema : failed to convert %s to json : %v", devfile, err))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer my format.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine. it's up to you

test/README.md Outdated Show resolved Hide resolved
@mmulholla
Copy link
Contributor Author

@maysunfaisal @yangcao77. Thanks for the comments would like to address term in my next PR if OK, nothing functional in the comments that would affect outcomes.

On a note the idea is that common code is common to both sides and is agnostic to which side is using it. To make this possible I added two interfaces in the common code for the api and library components to implement as necessary. Both need to implement the DevfileValidator and just the library needs to implement DevfileFollower. How this is then implemented is pretty standard for go - given the interface is defined in a different package to the implementor. If this is not what you expected please shout now.

One impact of this is that of this is that TestDevfile is now in common code but used in the api and library sides. In common code I can implement functions for it but I cannot in api and library so I had to modify some methods in api and library to take it as a parameter. If it was Java would have used "extends" but not sure that can be done in go. Would be interested if there is a better way. but for now I think this PR is good to go.

@mmulholla
Copy link
Contributor Author

@maysunfaisal @yangcao77 have now added a commit for all the things I planned to do in the next PR.

@yangcao77
Copy link
Contributor

yangcao77 commented Feb 22, 2021

I'm still feeling wired of this:

type DevfileValidator struct{}
// WriteAndVerify implements Saved.DevfileValidator interface.
// writes to disk and validates the specified devfile
func (devfileValidator DevfileValidator) WriteAndValidate(devfile *common.TestDevfile) error {

The empty struct DevfileValidator and the receiver function func (devfileValidator DevfileValidator) WriteAndValidate

I understand this is trying to resolve the cycle import issue, but it is very confusing when reading the code. Need to figure out a better way to make it more clear. But we can do it in the next PR.

My concerns have been resolved, just a minor typo as pointed out.
Waiting for Maysun's response as he also put some review comments

@mmulholla
Copy link
Contributor Author

Have pushed more changes for the comments I missed.

For info on the interface structure I worked from this: https://github.com/golang/go/wiki/CodeReviewComments#interfaces

@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: maysunfaisal, mmulholla
To complete the pull request process, please assign after the PR has been reviewed.
You can assign the PR to them by writing /assign in a comment when ready.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@mmulholla mmulholla merged commit 81859ea into devfile:master Feb 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants