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

Add basic integration test infrastructure (and new endpoint /api/v1/version for testing it) #741

Merged
merged 65 commits into from
Mar 6, 2017

Conversation

typeless
Copy link
Contributor

@typeless typeless commented Jan 24, 2017

The primary effort of the PR is to implement a prototype of (poor man's) automated functional tests for Gitea. It currently tests /install and /version only.

For #63

@typeless typeless changed the title Add endpoint for getting the server version [WIP] Add endpoint for getting the server version Jan 24, 2017
@lunny lunny added this to the 1.1.0 milestone Jan 24, 2017
@lunny lunny added pr/wip This PR is not ready for review modifies/api This PR adds API routes or modifies them type/feature Completely new functionality. Can only be merged if feature freeze is not active. labels Jan 24, 2017
@typeless
Copy link
Contributor Author

@lunny This is basically functioning and ready for review now.

@tboerger tboerger added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jan 24, 2017
@typeless typeless changed the title [WIP] Add endpoint for getting the server version Add endpoint for getting the server version Jan 24, 2017
@lunny lunny removed the pr/wip This PR is not ready for review label Jan 24, 2017
Makefile Outdated
@@ -67,7 +67,8 @@ lint:
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;

.PHONY: test
test:
test: TAGS=bindata sqlite
Copy link
Member

Choose a reason for hiding this comment

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

@tboerger maybe you can review this file changed.

Copy link
Contributor Author

@typeless typeless Jan 26, 2017

Choose a reason for hiding this comment

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

For the record, I used to add a new target like xtest: specifically for the new testing facility but go test would still look into the directory and keep doing its thing. Another approach to prevent it is to deliberately exclude the /tests/ directory from the PACKAGE variable for the xtest target.

Any ideas?

Edit: @lunny @tboerger I've changed it per the aforementioned way.

}

// RunTest Helper function for setting up a running Gitea server for functional testing and then gracefully terminating it.
func (c *Config) RunTest(tests ...func(*Config) error) (err error) {
Copy link
Member

Choose a reason for hiding this comment

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

Would it make sense to have the functions in tests also take a *testing.T argument? That way, the tests in tests can call assert.Equal(..) and the like.

Copy link
Contributor Author

@typeless typeless Jan 29, 2017

Choose a reason for hiding this comment

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

Agreed. I'll submit a change later for evaluation. And if it works well, I'll then adopt the assert.Equal way.

Edit: I have submitted the proposed change.


log.Printf("Actual: \"%s\" Expected: \"%s\"\n", string(actual), string(expected))
if actual != expected {
return fmt.Errorf("do not match")
Copy link
Member

Choose a reason for hiding this comment

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

This error message isn't very specific; if I see the error message "do not match", I don't know which test failed, why it failed (other than that something didn't match something else).

Like I said above, if we could find a way to pass a *testing.T into the tests, that would be really nice.

@@ -0,0 +1,11 @@
package misc
Copy link
Member

Choose a reason for hiding this comment

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

Need to include copyright info

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. 069155d249b94bb89a84a27002db177c072672c1

LogFile *os.File
}

func redirect(cmd *exec.Cmd, f *os.File) error {
Copy link
Member

Choose a reason for hiding this comment

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

The f argument is not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. a68c7ae


// Give the server some amount of time to warm up.
time.Sleep(100 * time.Millisecond)
fmt.Fprintf(os.Stderr, ".")
Copy link
Member

Choose a reason for hiding this comment

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

Can just use fmt.Fprint(os.Stderr, ".")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without the sleeps, the retry count would be around ~250 on my laptop. And I think the . with a fixed amount of timeout can give a rough metric on how the server startup time changes a long the way. If scalability really become an issue, we can change the timeout then.

Copy link
Member

Choose a reason for hiding this comment

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

No, I meant keep the sleep, but replace the call to fmt.Fprintf(..) (line 50) with fmt.Fprint(..). No reason to use fmt.Fprintf(..) if you're not using any formatting. Sorry for any confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it.

}
defer resp.Body.Close()

_ = resp
Copy link
Member

Choose a reason for hiding this comment

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

Is this line necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, it was for making debugging easier. OK to remove it now.


actual := string(bytes.TrimSpace(buf))

log.Printf("Actual: \"%s\" Expected: \"%s\"\n", string(actual), string(expected))
Copy link
Member

Choose a reason for hiding this comment

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

actual and expected are already strings; they don't need to be casted.


workdir := t.Config.WorkDir
if workdir == "" {
workdir, err = filepath.Abs(fmt.Sprintf("%s-%10d", filepath.Base(t.Config.Program), time.Now().UnixNano()))
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer something like ioutil.TempDir(os.TempDir(), "gitea_tests"). Since we're going to discard the contents of workdir anyways (line 78), we might as well use a temporary directory.

//LogFile: os.Stderr,
}

if err := utils.New(t, &conf).RunTest(install, version); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

It would be nice if we could find a way to not have to run install before every test. Once we start adding more end-to-end tests, this won't scale very well.

Copy link
Contributor Author

@typeless typeless Feb 1, 2017

Choose a reason for hiding this comment

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

I am thinking about adding a method func (t *T) Cleanup() to do the housekeeping. The tests we currently have would then look like utils.New(t, conf).RunTest(install, version).Cleanup().

But when used as follows to 'share' a testing instance across many testing functions:

var globalT *utils.T 

func init() {
    globalT = utils.New(t.conf).RunTest(install)
}
func TestA(t *testing.T) {
    globalT.RunTest(version)
}
func TestB(t *testing.T) {
    globalT.RunTest(signup)
}

I have no idea how we can call the cleanup method before quitting.

@bkcsoft
Copy link
Member

bkcsoft commented Feb 6, 2017

I don't see any unit-tests for /version ;P

Also please don't call it 'xtest', go for 'integration-test' or 'e2e-test' :)

@typeless
Copy link
Contributor Author

typeless commented Feb 8, 2017

@bkcsoft What do you mean by the 'unit-tests'? There isn't any under routers that I can copy either so I don't understand how it would be done.

@lunny
Copy link
Member

lunny commented Feb 8, 2017

build failed.

@typeless
Copy link
Contributor Author

typeless commented Feb 8, 2017

@lunny It's strange. My local copy doesn't have the problem and I can't see how this change could break it. I just renamed a Makefile target irrelevant to the unit tests.

@lunny
Copy link
Member

lunny commented Feb 8, 2017

Please rebase.

Copy link
Member

@bkcsoft bkcsoft left a comment

Choose a reason for hiding this comment

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

I didn't go through the tests, but they seem to pass 😉


// ServerVersion shows the version of the Gitea server
func ServerVersion(ctx *context.APIContext) {
ctx.Write([]byte(setting.AppVer))
Copy link
Member

Choose a reason for hiding this comment

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

As the entire API is JSON, maybe you should do this instead

type serverVersion struct {
    Version string
}
func ServerVersion(ctx *context.APIContext) {
    ctx.JSON(200, &serverVersion{Version: setting.AppVer})
}

Preferably the struct should go in code.gitea.io/sdk 🙂 (If you do that just call it api.Version)

Copy link
Contributor Author

@typeless typeless Feb 21, 2017

Choose a reason for hiding this comment

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

There exists an API named Version already (https://github.com/go-gitea/gitea/blob/master/vendor/code.gitea.io/sdk/gitea/gitea.go#L17) for library's version.

I am afraid that it would lead to confusion if I have the both called 'Version'.
I did change the function name of the server-side handler to Version. PTAL.

@typeless typeless changed the title Add endpoint for getting the server version Add basic integration test (and new endpoint /api/v1/version for testing it) Feb 22, 2017
@typeless typeless changed the title Add basic integration test (and new endpoint /api/v1/version for testing it) Add basic integration test infrastructure (and new endpoint /api/v1/version for testing it) Feb 22, 2017
@lunny
Copy link
Member

lunny commented Feb 22, 2017

@typeless is this ready to review now?

@typeless
Copy link
Contributor Author

@lunny Yes.


"github.com/stretchr/testify/assert"

"code.gitea.io/gitea/tests/internal/utils"
Copy link
Member

Choose a reason for hiding this comment

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

https://github.com/go-gitea/gitea/blob/master/CONTRIBUTING.md#styleguide

import (
  // stdlib
  "encoding/json"
  "fmt"

  // local packages
  "code.gitea.io/gitea/models"
  "code.gitea.io/sdk/gitea"

  // external packages
  "github.com/foo/bar"
  "gopkg.io/baz.v1"
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


fields := strings.Fields(string(out))
if len(fields) != 3 {
return fmt.Errorf("unexpected version string")
Copy link
Member

Choose a reason for hiding this comment

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

Minor, but could we include the unexpected version string in the error message; it would make debugging easier in the case where there is unexpected output.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea.

@typeless
Copy link
Contributor Author

typeless commented Feb 23, 2017

For the record I just found the tests can not pass if using the Go tip, but works fine with Go 1.8. 😮

EDIT: Git bisect shows that it's golang/go@3792db5

Copy link
Member

@strk strk left a comment

Choose a reason for hiding this comment

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

Could integration tests be put under a specific directory rather than just the generic /test/ one ?


func makeSimpleSettings(user, workdir, port string) map[string][]string {
return map[string][]string{
"db_type": {"SQLite3"},
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this need a build tag to work ?
Any chance to test other databases too ?

Copy link
Contributor Author

@typeless typeless Feb 23, 2017

Choose a reason for hiding this comment

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

Doesn't this need a build tag to work ?

Yes. Currently we need to have an existing Gitea binary built with SQLite3 to work. I have added a Makefile target named 'e2e-test' to simplify the steps.

Any chance to test other databases too ?

I have not used other databases for Gitea so far and they are much harder to setup. Therefore I would delegate the task to other developers with the skills & experiences.

return map[string][]string{
"db_type": {"SQLite3"},
"db_host": {"localhost"},
"db_path": {workdir + "data/gitea.db"},
Copy link
Member

Choose a reason for hiding this comment

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

But the test db data will stay with production data?

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 'workdir' is created by ioutil.TempDir if not specified (that is, an empty string).

My comment regarding the field WorkDir is outdated and does not match with the reality. I'll fix it. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@strk
Copy link
Member

strk commented Mar 4, 2017 via email

@typeless
Copy link
Contributor Author

typeless commented Mar 5, 2017

Was the PR merged already ? Can you drop a link to the sdk PR here ?

go-gitea/go-sdk#43

@andreynering
Copy link
Contributor

andreynering commented Mar 5, 2017

LGTM

Just missing @bkcsoft approval.

@tboerger tboerger added lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. and removed lgtm/need 1 This PR needs approval from one additional maintainer to be merged. labels Mar 5, 2017
@typeless
Copy link
Contributor Author

typeless commented Mar 6, 2017

@bkcsoft Please take a look at the PR.

@lunny lunny merged commit 8482936 into go-gitea:master Mar 6, 2017
@lunny
Copy link
Member

lunny commented Mar 7, 2017

This will produce integrationsdata, integrationslog and integrationsrepositories, that should be a bug. @typeless

@typeless typeless deleted the add-endpoint-for-version branch April 3, 2019 04:59
@go-gitea go-gitea locked and limited conversation to collaborators Nov 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/done This PR has enough approvals to get merged. There are no important open reservations anymore. modifies/api This PR adds API routes or modifies them type/feature Completely new functionality. Can only be merged if feature freeze is not active. type/testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants