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

Replace the current e2e script with a test suite running e2e tests. #1514

Merged
merged 2 commits into from
Feb 19, 2020

Conversation

fedepaol
Copy link
Member

What is the problem I am trying to address?
Right now the e2e tests are performed by a non trivial bash script, difficult to extend with new tests.
This pr replace it with a go - baked e2e test suite, right now adding the same tests we have in the bash script plus one using a wrong GOPROXY variable.

This should be easier to maintain / extend.

How is the fix applied?

By implementing a new test suite that builds athens and interacts directly with go.

Mention the issue number it fixes or add the details of the changes if it doesn't have a specific issue.

Fixes #1474

@fedepaol fedepaol requested a review from a team as a code owner December 30, 2019 13:22
@ghost ghost self-assigned this Jan 20, 2020
@ghost
Copy link

ghost commented Jan 20, 2020

Assigned myself to remember to try this out and go over it in more detail. But I like it.

@fedepaol
Copy link
Member Author

fedepaol commented Feb 5, 2020

@robjloranger @arschles any chance to give a push to this?

@ghost
Copy link

ghost commented Feb 5, 2020

I'm so sorry @fedepaol, I missed it again. I've been working too much at my day job. I will do this on the weekend at the latest.

@fedepaol
Copy link
Member Author

fedepaol commented Feb 6, 2020

@robjloranger no problem! I was just going through blocked PRs of mine and I remembered about this. Take your time, and thanks!

@ghost
Copy link

ghost commented Feb 11, 2020

testing now, finally

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Looks good to me, other than one line ending 😃

appveyor.yml Outdated
- go test --tags unittests ./...
Copy link

Choose a reason for hiding this comment

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

silly newline missing

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@fedepaol
Copy link
Member Author

Looks good to me, other than one line ending smiley

Thanks for your review 👍

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

just waiting for the drone ci to pass

Copy link
Contributor

@marwan-at-work marwan-at-work left a comment

Choose a reason for hiding this comment

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

Just the one comment, but otherwise nice work :)

.drone.yml Outdated
@@ -28,7 +28,7 @@ steps:
# test
- ./scripts/check_gofmt.sh
- go vet ./...
- go test -v ./...
- go test --tags unittests -v ./...
Copy link
Contributor

@marwan-at-work marwan-at-work Feb 11, 2020

Choose a reason for hiding this comment

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

Just checking: this means that go test ./... will always try to run e2e tests no?
In other words, everytime you want to run the unit tests you have to pass that tag.

If that's true, then it would be more correct to say go test --tags e2e instead . Thoughts?

Copy link

Choose a reason for hiding this comment

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

Good call, if true then defaulting to unit tests and hiding e2e behind a flag would be a better UX.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, and I agree. I will change the build tag to be selective for e2e tests, so the default one is for plain unit tests.

Copy link
Contributor

@marwan-at-work marwan-at-work left a comment

Choose a reason for hiding this comment

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

Thanks for doing this :) I think the PR can definitely use some tightening up but otherwise awesome work 👍

"time"
)

func buildAthens(goBin string, destPath string, env []string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: goBin, destPath string -- no need to declare the type twice.

}

cmd := exec.Command(goBin, "build", "-o", target, binFolder)
cmd.Env = env
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd add a bytes.Buffer to cmd.Stderr and return it in case of error because then it will explain why go build failed.


func stopAthens() error {
cmd := exec.Command("pkill", "athens-proxy")
err := cmd.Run()
Copy link
Contributor

Choose a reason for hiding this comment

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

i'd either just return cmd.Run() or properly populate stdout/stderr

cmd := exec.Command(athensBin)
cmd.Env = env

go func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

why not just go cmd.Run() ?

Copy link
Contributor

Choose a reason for hiding this comment

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

and if you are trying to run the command in the background, it is more appropriate to use cmd.Start(): https://golang.org/pkg/os/exec/#Cmd.Start

Copy link
Member Author

Choose a reason for hiding this comment

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

and if you are trying to run the command in the background, it is more appropriate to use cmd.Start(): https://golang.org/pkg/os/exec/#Cmd.Start

Ah, nice!

}()

ticker := time.NewTicker(time.Second)
timeout := time.After(2 * time.Minute)
Copy link
Contributor

Choose a reason for hiding this comment

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

two minutes seems a lil crazy to wait for athens to start 😄 -- let's make it 20 seconds?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, I am getting deviated to k8s timescales

return target, err
}

func stopAthens() error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a better way to "stopAthens" is to have the runAthensAndWait take a context that you can cancel whenever you want to stop athens and just pass that context into https://golang.org/pkg/os/exec/#CommandContext

which should render this whole function unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

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

Did not know about it, thanks!

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, yes and no, as I am using stopAthens also to remove any dangling instance before running the real tests. So it's ok for the teardown phase, but I'll keep this around as well.

if err != nil {
m.Fail("Failed to stop athens", err)
}
chmodR(m.tmpDir, 0777)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a cleaner way to do this is to just call clean modcache -- I think we should probably do it on the go_get_fetcher as well. But that's another topic :)

Copy link
Member Author

Choose a reason for hiding this comment

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

I do agree to clear the cache instead of brutally erasing in SetupTest, as there we care only about the cache to be empty.
In TearDown though, I'd like to remove any additional folder that was created by the test suite, and I am afraid clearing the cache is not enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

@fedepaol right you can still remove the folder, but there won't be a need to chmod anything :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes I left it there as I did not remember why I added originally. I'll try to remove it and see if it works :-)

m.Fail("Failed to make temp dir", err)
}

m.goModCache = path.Join(m.tmpDir, "pkg", "mod")
Copy link
Contributor

Choose a reason for hiding this comment

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

I would probably make two temp directories to maintain a nicer separation: one for GOPATH and one outside of GOPATH for happy-path. This way you don't to actually care about the "pkg/mod" part here, and cleaning the cache only needs to take the GOPATH env var and nothing else

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

@arschles arschles left a comment

Choose a reason for hiding this comment

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

@fedepaol sorry I got sidetracked and didn't review this. It looks great 🎉 :shipit: 🚀 ! @marwan-at-work can we address your comments in a follow-up PR? I can submit it if @fedepaol. I would love to get this into master so that I can expand on the tests...

@fedepaol
Copy link
Member Author

@arschles I think I addressed all the comments in my latest push of yesterday.
@marwan-at-work would you mind giving another look?

Copy link
Contributor

@marwan-at-work marwan-at-work left a comment

Choose a reason for hiding this comment

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

@arschles I added a couple of more comments but hitting approve if we want to tighten things up in a follow up PR -- happy to do it as well.

Thanks again @fedepaol :)

suite.Suite
goBinaryPath string
env []string
tmpDir string
Copy link
Contributor

Choose a reason for hiding this comment

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

i'd call it goPath or GOPATH to know what the tmpDir is for :)

// ignoring error as if no athens is running it fails.

ctx := context.Background()
ctx, m.stopAthens = context.WithCancel(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Form the context package docs:

Do not store Contexts inside a struct type; instead, pass a Context explicitly to each function that needs it. The Context should be the first parameter.

I realize storing the context is necessary here because of testify/suite, but I'd rather we followed best practices instead of having the framework steer us away form that.

That said, we can definitely do it in a follow up PR because it means removing the test suite from the e2e tests :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah right. That would make things less easy. Not even sure if it's worth reverting to the previous stopAthens, as even if we remove testify having a propagated context will bloat the code a bit.

We want e2e tests to be skipped while running normal unit tests.
@fedepaol
Copy link
Member Author

@marwan-at-work I applied the change suggested in #1514 (comment) .
I am not sure about the context thing though. We need to spin up athens when the "suite" (or the set of tests) start, and to stop it when the "suite" is complete, so I can't see a clean way to have the context not stored and propagated through functions.
I feel like the best approach is to revert to the previous "stop" function. Wdyt?

@marwan-at-work
Copy link
Contributor

@fedepaol IMHO the best way is to just use the standard library because the std lib wouldn't get in your way the same way this test suite does :)

That said, we can keep things the way they are because it works, then remove them and use regular table tests a follow up pr

@fedepaol
Copy link
Member Author

@fedepaol IMHO the best way is to just use the standard library because the std lib wouldn't get in your way the same way this test suite does :)

That said, we can keep things the way they are because it works, then remove them and use regular table tests a follow up pr

Ok, we can discuss those details later then. Thanks again for your review!

@fedepaol
Copy link
Member Author

So this can be merged right?

@arschles arschles merged commit 27f3683 into gomods:master Feb 19, 2020
@arschles
Copy link
Member

@fedepaol thank you * 💯 for your hard work on this PR!

@arschles arschles mentioned this pull request Feb 19, 2020
@mplachter
Copy link
Contributor

mplachter commented Feb 25, 2020

Heads up this did break the docker-e2e-tests. I'm currently fixing to test the new redis changes will get a MR up to fix the docker-e2e-tests (this might take me a bit just a heads up if someone wants to fix it before me go-ahead)

test_e2e.sh doesn't exist anymore.

  teste2e:
    build:
      context: .
      dockerfile: Dockerfile.test
      args:
        GOLANG_VERSION: 1.13
    command: ["./scripts/test_e2e.sh"]

@arschles
Copy link
Member

@mplachter would it help if I go ahead and fix docker-e2e-tests in a separate PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expand the e2e tests
4 participants