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

Focus option for top level tests #329

Closed
sksamuel opened this issue May 14, 2018 · 24 comments
Closed

Focus option for top level tests #329

sksamuel opened this issue May 14, 2018 · 24 comments
Assignees
Labels
enhancement ✨ Suggestions for adding new features or improving existing ones.

Comments

@sksamuel
Copy link
Member

sksamuel commented May 14, 2018

Prefix a test with f: (top level only) and that test (or group of tests) will be the only ones executed.

@sksamuel sksamuel self-assigned this May 14, 2018
@sksamuel sksamuel added the enhancement ✨ Suggestions for adding new features or improving existing ones. label May 14, 2018
@sksamuel sksamuel removed their assignment May 14, 2018
@sksamuel sksamuel added this to the 3.2 milestone May 14, 2018
@sksamuel sksamuel changed the title Feature: Focus option for top level tests Focus option for top level tests May 14, 2018
@sksamuel sksamuel removed this from the 3.2 milestone May 15, 2018
@sksamuel sksamuel self-assigned this May 15, 2018
sksamuel added a commit that referenced this issue May 15, 2018
@bbaldino
Copy link
Contributor

This is awesome!

@sksamuel
Copy link
Member Author

It's in 3.1.1 if you want to use it :)

@dave08
Copy link
Contributor

dave08 commented Jan 7, 2019

@sksamuel Does this work in all test types?

@sksamuel
Copy link
Member Author

Should work for all, but only top level tests. @dave08

@dave08
Copy link
Contributor

dave08 commented Jan 10, 2019

It would be great if it could work for groupings and top level tests, since in KotlinTest there's no IDE arrows like in Spek and JUnit besides each test, so one has to run the whole class or disable all the other tests just to concentrate on the one test he/she's developing... @sksamuel Or is there another way to do that? Also, you mean that test("f:Test one") { } works? Or does one have to provide it through options? Also, the ! is a convenient shortcut even for other test types, does the user absolutely need the options() function to provide it?

@sksamuel
Copy link
Member Author

If you put f: in front of your test name then only that test (and nested tests under it) will be executed @dave08
Eg,

See

https://github.com/kotlintest/kotlintest/blob/master/kotlintest-tests/kotlintest-tests-core/src/test/kotlin/com/sksamuel/kotlintest/FocusTest.kt

I'm not sure what you mean by your second comment about ! and options.

@dave08
Copy link
Contributor

dave08 commented Jan 10, 2019

Say:

class FooTest : DescribeSpec({
	describe("A foo") {
		context("!Planned feature (not yet working on this)") {
			// ... All the tests are skipped/disabled under here because of the ! prefix
		}

		context("Feature already finished") {
			// ... These tests should run when there are no `f:`s
		}

		context("f:Current feature") {
			// ... Only these tests should run as long as there's `f:` here
		}
	}
})

@sksamuel

@sksamuel
Copy link
Member Author

I see, no you can't do that. The reason is, inner tests are not known until runtime. So it would break the way the test runners work.

You can put the f: on the describe block.

@dave08
Copy link
Contributor

dave08 commented Jan 10, 2019

So how does providing the options() work in it(), one could disable the test there... if when adding the test you check the label string to make the same decision it would be possible no? At least for !... I don't think I saw a parameter for f: in the options(), maybe that's what you mean is impossible? I was actually wondering why there's no focus param there... @sksamuel

I suppose the multi-level f: or focus on option is too hard to currently implement, so I shouldn't open a seperate issue about this feature (this is probably the wrong issue to be discussing this know that I understand the title better...)?

I feel this feature is pretty important given that there aren't any arrows to use to run individual cases in the IDE. Maybe this could be implemented under the hood using one test per class with an internal marking that other tests should not be run?

@sksamuel
Copy link
Member Author

In order to determine which test to run, it has to check all of them in the same scope.

If you do:

  test("test 1") { }
  test("f: test 2") { }

Then test 1 needs to be skipped because you've focused test 2. So it needs to scan ahead. We can't do this in nested scopes as the test closures are executed lazily, so that variable initialisation etc, works properly.

@dave08
Copy link
Contributor

dave08 commented Jan 11, 2019

So maybe have a f2: on each level scope to focus on the second (or whatever) item on the level under it? A bit harder to use, but may be easier to know at run time what to run @sksamuel.

Sorry for insisting, its fine if you just say its not possible and thats it, I'm just trying to see if there's a workable solution, I think its a nice addition to a dev's workflow.

@sksamuel
Copy link
Member Author

That's not the problem.
The problem is that you have to look ahead. If you mark test 20 with f: or f2, then the engine has to skip the first 19. It can only know to do this if it has already scanned the complete list of test names.

@dave08
Copy link
Contributor

dave08 commented Jan 11, 2019

I mean f2 would be on the parent to indicate the second test or group under it is focused so you know before running what's under it

@sksamuel
Copy link
Member Author

You mean f2 would indicate the 2nd test was focused, and f3 the third test and so on?

@dave08
Copy link
Contributor

dave08 commented Jan 13, 2019

Yes, the second test under the indicated scope, but a clearer naming might be chosen to indicate not focusing on the item with the f but its child maybe f-2: (like the freespec group indicator - ) or 2> or >2 ?

It might get complicated in parameterized tests, I don't know if it would be possible to run the whole parameter set (not just the 4th one for eg.), which makes I think more sense in the devs workflow.

@TAGC
Copy link

TAGC commented Feb 20, 2019

I see, no you can't do that. The reason is, inner tests are not known until runtime. So it would break the way the test runners work.

Yeah, this is pretty annoying. Using DescribeSpec, I need to literally comment out every test but the one I want to focus on in order to isolate it.

@LeoColman
Copy link
Member

LeoColman commented Feb 20, 2019 via email

@sksamuel
Copy link
Member Author

sksamuel commented Feb 20, 2019 via email

@TAGC
Copy link

TAGC commented Feb 20, 2019

Oh, I didn't realise there was a plugin, that's neat.

I just installed it and now notice there's arrows in the IDE beside each individual test case (within a DescribeScope). However, clicking any of them just runs all the test cases, the same as if I click the arrow beside the top-level "describe(...)". Should the plugin support running individual nested test cases?

This is what I mean:

idea64_2019-02-20_12-11-39

@LeoColman
Copy link
Member

It will actually make focus a bit redundant.

Not redundant if you consider people still use eclipse

@sksamuel
Copy link
Member Author

sksamuel commented Feb 20, 2019 via email

@sksamuel
Copy link
Member Author

@TAGC You're the second person to say this. Although the "run" tool tip is wrong (I don't know how to fix that currently), for me it does only run the correct single test. Can you try it, and take a screenshot of the run configuration page.

@TAGC
Copy link

TAGC commented Feb 20, 2019

Sure, the run configuration (this is used regardless of which green arrow I click):

idea64_2019-02-20_12-39-08

And here's the test output pane:

idea64_2019-02-20_12-40-40

Here's the relevant logging output:

40 [main] DEBUG KotlinTestEngine - configurationParameters=LauncherConfigurationParameters []
40 [main] DEBUG KotlinTestEngine - uniqueId=[engine:kotlintest]
60 [main] DEBUG KotlinTestEngine - LauncherDiscoveryRequest [
classpathRootSelectors=[]
classpathResourceSelectors=[]
classSelectors=[com.mycompany.testmaster.domain.nodes.CompositeNodeTests]
methodSelectors=[]
directorySelectors=[]
fileSelectors=[]
moduleSelectors=[]
packageSelectors=[]
uniqueIdSelectors=[]
uriSelectors=[]
engineFilters=[]
postDiscoveryFilters=[]
classnameFilters=[]
packageNameFilters=[]
]
120 [main] DEBUG TestDiscovery - Loaded 1 classes from classnames...
395 [main] DEBUG TestDiscovery - ...which has filtered to 1 non abstract classes
395 [main] DEBUG TestDiscovery - 1 classes after applying discovery extensions405 [main] DEBUG KotlinTestEngine - configurationParameters=LauncherConfigurationParameters []
405 [main] DEBUG KotlinTestEngine - uniqueId=[engine:kotlintest]
405 [main] DEBUG KotlinTestEngine - LauncherDiscoveryRequest [
classpathRootSelectors=[]
classpathResourceSelectors=[]
classSelectors=[com.mycompany.testmaster.domain.nodes.CompositeNodeTests]
methodSelectors=[]
directorySelectors=[]
fileSelectors=[]
moduleSelectors=[]
packageSelectors=[]
uniqueIdSelectors=[]
uriSelectors=[]
engineFilters=[]
postDiscoveryFilters=[]
classnameFilters=[]
packageNameFilters=[]
]
415 [main] DEBUG KotlinTestEngine - JUnit execution request [configurationParameters=LauncherConfigurationParameters []; rootTestDescriptor=KotlinTestEngineDescriptor: [engine:kotlintest]]
415 [main] DEBUG JUnitTestRunnerListener - Engine started; classes=[[class com.mycompany.testmaster.domain.nodes.CompositeNodeTests]]
415 [main] DEBUG TestEngine - Submitting 1 specs
415 [main] DEBUG TestEngine - Waiting for spec execution service to terminate
437 [kotlintest-engine-0] DEBUG JUnitTestRunnerListener - prepareSpec [Description(parents=[], name=CompositeNodeTests)]447 [kotlintest-test-executor-0] DEBUG JUnitTestRunnerListener - Creating test case descriptor Description(parents=[CompositeNodeTests], name=Describe: Composite node)/Container
457 [kotlintest-test-executor-0] DEBUG JUnitTestRunnerListener - Notifying junit of start event [engine:kotlintest]/[spec:CompositeNodeTests]/[test:Describe%3A Composite node]457 [kotlintest-test-executor-0] DEBUG JUnitTestRunnerListener - Creating test case descriptor Description(parents=[CompositeNodeTests, Describe: Composite node], name=Scenario: immediately executes once and terminates if it has no inputs and no outputs)/Test
457 [kotlintest-test-executor-0] DEBUG JUnitTestRunnerListener - Notifying junit of start event [engine:kotlintest]/[spec:CompositeNodeTests]/[test:Describe%3A Composite node]/[test:Scenario%3A immediately executes once and terminates if it has no inputs and no outputs]
634 [kotlintest-engine-0] DEBUG JUnitTestRunnerListener - Notifying junit of test case completion [engine:kotlintest]/[spec:CompositeNodeTests]/[test:Describe%3A Composite node]=TestResult(status=Failure, error=java.lang.AssertionError: Expected exception java.lang.IllegalStateException but no exception was thrown, reason=null, metaData={})

@sksamuel
Copy link
Member Author

sksamuel commented Feb 20, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ✨ Suggestions for adding new features or improving existing ones.
Projects
None yet
Development

No branches or pull requests

5 participants