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

More cmd/ refactoring to simplify test loading and support integration tests #2412

Merged
merged 10 commits into from
Mar 18, 2022

Conversation

na--
Copy link
Member

@na-- na-- commented Mar 6, 2022

More yak shaving, but after this, some parts of cmd/ are almost normal looking 😅 🎉 I particularly like how clean cmd/archive.go became 🎉

k6/cmd/archive.go

Lines 44 to 72 in 147e3d1

RunE: func(cmd *cobra.Command, args []string) error {
test, err := loadTest(gs, cmd, args, getPartialConfig)
if err != nil {
return err
}
// It's important to NOT set the derived options back to the runner
// here, only the consolidated ones. Otherwise, if the script used
// an execution shortcut option (e.g. `iterations` or `duration`),
// we will have multiple conflicting execution options since the
// derivation will set `scenarios` as well.
err = test.initRunner.SetOptions(test.consolidatedConfig.Options)
if err != nil {
return err
}
// Archive.
arc := test.initRunner.MakeArchive()
f, err := gs.fs.Create(archiveOut)
if err != nil {
return err
}
err = arc.Write(f)
if cerr := f.Close(); err == nil && cerr != nil {
err = cerr
}
return err
},

Closes #342

@na-- na-- added this to the v0.38.0 milestone Mar 6, 2022
@na--
Copy link
Member Author

na-- commented Mar 7, 2022

With the latest commit here, we can now write dead-simple and safe integration tests 🎉 See this for an example:

func TestSimpleTestStdin(t *testing.T) {
t.Parallel()
ts := newGlobalTestState(t)
ts.args = []string{"k6", "run", "-"}
ts.stdIn = bytes.NewBufferString(noopDefaultFunc)
newRootCommand(ts.globalState).execute()
stdOut := ts.stdOut.String()
assert.Contains(t, stdOut, "default: 1 iterations for each of 1 VUs")
assert.Contains(t, stdOut, "1 complete and 0 interrupted iterations")
assert.Empty(t, ts.stdErr.Bytes())
assert.Empty(t, ts.loggerHook.Drain())
}

So between this and the fact that we have xk6 integration tests in our CI, I think it's pretty safe to close #342 once this PR is merged 🎉

@na-- na-- linked an issue Mar 7, 2022 that may be closed by this pull request
@na-- na-- changed the title Further refactor cmd/ to simplify and unify test loading Further refactor cmd/ to simplify test loading and support integration tests Mar 7, 2022
@na--
Copy link
Member Author

na-- commented Mar 7, 2022

And yeah, I consider these to be integration tests because this is what main.go does now:

k6/main.go

Lines 23 to 29 in 441a8f0

import (
"go.k6.io/k6/cmd"
)
func main() {
cmd.Execute()
}

k6/cmd/root.go

Lines 297 to 301 in 441a8f0

func Execute() {
gs := newGlobalState(context.Background())
newRootCommand(gs).execute()
}

And this is what an integration test in cmd/ can do:

ts := newGlobalTestState(t)
ts.args = []string{"k6", "run", "-"}
ts.stdIn = bytes.NewBufferString(noopDefaultFunc)
newRootCommand(ts.globalState).execute()

The two are basically the same, only the integration test has a dedicated environment (so we can run it safely in parallel) and also complete control that environment 🎉

@na-- na-- changed the title Further refactor cmd/ to simplify test loading and support integration tests More cmd/ refactoring to simplify test loading and support integration tests Mar 7, 2022
@na-- na-- mentioned this pull request Mar 7, 2022
@na-- na-- force-pushed the cleanup-5 branch 2 times, most recently from 7574bd2 to 691be6b Compare March 7, 2022 13:25
Copy link
Member

@oleiade oleiade left a comment

Choose a reason for hiding this comment

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

Thumbs up from me 👍 🎉 Kudos for those changes, I do believe they will make our lives easier indeed!

I do think it would be beneficial to find better names for some of the APIs introduced in this PR; see my comments smiley 🐱

cmd/test_load.go Show resolved Hide resolved
cmd/test_load.go Outdated Show resolved Hide resolved
cmd/test_load.go Outdated Show resolved Hide resolved
cmd/test_load.go Show resolved Hide resolved
cmd/test_load.go Show resolved Hide resolved
cmd/test_load.go Show resolved Hide resolved
cmd/runtime_options.go Show resolved Hide resolved
oleiade
oleiade previously approved these changes Mar 16, 2022
Copy link
Member

@oleiade oleiade left a comment

Choose a reason for hiding this comment

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

Besides my few comments on naming, looking good! The yak is shaved, and we're equipped to make ourselves a nice pull-over for the next winter. Kudos 🎉

Base automatically changed from cleanup-4 to master March 16, 2022 15:50
This actually also fixes a minor bug where the CLI flag was available in `k6 run` and `k6 inspect`, but it wasn't available in `k6 cloud` and `k6 archive`.
runtimeOptions lib.RuntimeOptions
metricsRegistry *metrics.Registry
builtInMetrics *metrics.BuiltinMetrics
initRunner lib.Runner // TODO: rename to something more appropriate
Copy link
Contributor

Choose a reason for hiding this comment

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

Just runner I mean it seems to be the only runner either way.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe, but I'd prefer to wait with the final refactor and rename before messing with the names more...

Copy link
Contributor

@mstoykov mstoykov left a comment

Choose a reason for hiding this comment

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

LGTM in general. I have some naming comments that can be addressed in a separate PR

Comment on lines +206 to -213
hardStop := func(sig os.Signal) {
logger.WithField("sig", sig).Error("Aborting k6 in response to signal, we won't wait for the test to end.")
os.Exit(int(exitcodes.ExternalAbort))
}()
Copy link
Contributor

Choose a reason for hiding this comment

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

The names here are not ... good IMO.

I was really confused that gracefulStop does something while hardStop just logs and does not os.Exit.

I would argue they are not great in the handleTestAbortSignals either.

I would recommend adding on in front the names in all places. This still isn't great, but I feel a lot better about onHardStop not calling os.Exit explicitly and only logging, while onGracefulStop actually doing something.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or maybe just have os.Exit in both hardStops 🤷 I kind of feel like this DRY-ing of the code isn't really worth it

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 for gracefulStop and onHardStop
Regarding the DRY, keep in mind that this will be used at least 2 more times, in k6 coordinate and k6 agent

Copy link
Member Author

Choose a reason for hiding this comment

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

(for expediency, I will address this in the next PR)

Comment on lines +110 to +112
if secondHandler != nil {
secondHandler(sig)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: is this nil check needed?

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 think so, if os.Exit() is here. And I kind of like it to be here, to softly force the user to acknowledge that a second Ctrl+C should always abort the execution almost immediately, not be something optional.

Comment on lines +44 to +45
TestType null.String `json:"-"`

Copy link
Contributor

Choose a reason for hiding this comment

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

We do actually write this in the archive under type

https://github.com/grafana/k6/blob/master/js/bundle.go#L190

maybe one day we can make MakeArchive outside of a Runner 🤷

@na-- na-- merged commit 0b23c2a into master Mar 18, 2022
@na-- na-- deleted the cleanup-5 branch March 18, 2022 11:18
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.

More robust integration tests
3 participants