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

Introduce fail-fast feature for dynamic test execution #838

Closed
wants to merge 11 commits into from

Conversation

sormuras
Copy link
Member

@sormuras sormuras commented May 5, 2017

Overview

This PR provides tools around the dynamic tests feature to accomplish a scenario-like way of expressing related tests. The new factory method DynamicTest.requiredTest(String displayName, Executable executable) creates dynamic test instances, that require to finish successfully. If the dynamic test execution loop detects an unsuccessful required test, it stops the loop immediatly. This can happen at any dynamic container level. If the execution loop is halted, no further dynamic test is registered and therefore not executed.

Example usage

Copied from DynamicTestsDemo.java with Log-in and third page visit being required dynamic test. They require to finish with a successful TestExecutionResult

dynamicTest("Visit page requiring authorization while not logged in", () -> {
	// attempt to visit page which requires that a user is logged in
	// assert user is redirected to login page
}),
requiredTest("Log-in", () -> {
	// submit login form with valid credentials
	// assert user is redirected back to previous page requiring authorization
	// assertTrue(false, "you shall not pass");
}),
dynamicContainer("Can access several pages while logged in",
	dynamicTest("Visit second page requiring authorization while logged in", () -> {
		// visit another page which requires that a user is logged in
		// assert user can access page
	}),
	requiredTest("Visit third page requiring authorization while logged in", () -> {
		// visit another page which requires that a user is logged in
		// assert user can access page
		// assertTrue(false, "exit here - no fourth page, not log out");
	}),
	dynamicTest("Visit fourth page requiring authorization while logged in", () -> {
		// visit another page which requires that a user is logged in
		// assert user can access page
	})
),
dynamicTest("Log-out", () -> {
	// visit logout URL
	// assert user has been logged out
})
├─ dynamicNodesWithRequiredTests() ✘
│  ├─ Visit page requiring authorization while not logged in ✔
│  └─ Log-in ✘ you shall not pass
  • if "Visit third page..." fails, "Visit fourth page..." and "Log-out" won't show up
├─ dynamicNodesWithRequiredTests() ✘
│  ├─ Visit page requiring authorization while not logged in ✔
│  ├─ Log-in ✔
│  └─ Can access several pages while logged in ✘
│     ├─ Visit second page ... logged in ✔
│     └─ Visit third page ... logged in ✘ exit here - no fourth page, not log out

Related issues

Deliverables

  • Discuss, if we want to add this requiredTest(...) feature - if yes, finish Definition of Done list below

I hereby agree to the terms of the JUnit Contributor License Agreement.


Definition of Done

@nipafx
Copy link
Contributor

nipafx commented May 5, 2017

If you end up not using merging this, there is a small side project I could recommend. 😉

@sbrannen
Copy link
Member

sbrannen commented May 5, 2017

Please note that the "blocking" feature you implemented in this PR is directly related to #431.

@sormuras sormuras changed the title Introduce lightweight scenario support via dynamic tests Introduce fail-fast feature in dynamic tests May 5, 2017
@mfulton26
Copy link

mfulton26 commented May 5, 2017

I think there needs to be a way to specify a blocking container named something like dynamicSteps, dynamicStepContainer, dynamicScenario, etc. e.g.:

    @TestFactory
    @DisplayName("Web Security Scenario")
    Stream<DynamicNode> scenarioTests() {
        return Stream.of(
                dynamicTest("Visit page requiring authorization while not logged in", () -> {
                    // attempt to visit page which requires that a user is logged in
                    // assert user is redirected to login page
                }),
                dynamicScenario("Log-in", Stream.of(
                    dynamicStep("Log-in button is disabled", () -> {
                        // assert user cannot submit login form without entering credentials
                    }),
                    dynamicStep("Log-in button becomes enabled after entering credentials", () -> {
                        // assert log-in button is enabled once credentials are entered
                    }),
                    dynamicStep("Visit third page requiring authorization while logged in", () -> {
                        // submit login form with valid credentials
                        // assert user is redirected back to previous page requiring authorization
                        // fail("you shall not pass");
                    })
                )),
                dynamicContainer("Can access several pages while logged in", Stream.of(
                    dynamicTest("Visit second page requiring authorization while logged in", () -> {
                        // visit another page which requires that a user is logged in
                        // assert user can access page
                    }),
                    dynamicTest("Visit third page requiring authorization while logged in", () -> {
                        // visit another page which requires that a user is logged in
                        // assert user can access page
                    })
                )),
                dynamicTest("Log-out", () -> {
                    // visit logout URL
                    // assert user has been logged out
                })
        );
    }

@sormuras sormuras changed the title Introduce fail-fast feature in dynamic tests Introduce requiredTest(...) in DynamicTest May 5, 2017
@sormuras
Copy link
Member Author

sormuras commented May 5, 2017

Description updated.

@mfulton26 Does the new required strategy meet your needs?

@mfulton26
Copy link

I believe so. Thank you.

@sormuras
Copy link
Member Author

sormuras commented May 7, 2017

DynamicTest.requiredTest(...) is not the best name. What other name could we use to describe "a dynamic test that has the power to halt the execution loop of the @TestFactory-annotated method"?

replace "dynamic" and leave "Test"

  • DynamicTest.requiredTest
  • DynamicTest.essentialTest
  • DynamicTest.gatewayTest

leave "dynamic" and replace "Test"

  • DynamicTest.dynamicCheckPoint
  • DynamicTest.dynamicGuard
  • DynamicTest.dynamicBarrier
  • DynamicTest.dynamicStep

@mlevison
Copy link

mlevison commented May 7, 2017 via email

@sormuras
Copy link
Member Author

sormuras commented May 7, 2017

[...] It is called after each step is executed.

Mh. How do you pass the method (or any other callback handle) to the execution cycle? Can this "registerPredicateEvaluatedAfterEachDynamicTest(this::shouldContinue);" called more than once?

Perhaps the quality of any of these names would easier to judge of there
was a sample code fragment.

Look at the description text of this issue; it uses requiredTest.

@mlevison
Copy link

mlevison commented May 7, 2017 via email

@sormuras
Copy link
Member Author

sormuras commented May 8, 2017

What about adding an optional parameter to DynamicTest.dynamicTest(String, Executable, Predicate) that is evaluated after the executable ran. If it evaluates to true the dynamic test execution proceeds, or otherwise terminates.

@sormuras sormuras changed the title Introduce requiredTest(...) in DynamicTest Introduce fail-fast feature for dynamic test execution May 8, 2017
@mlevison
Copy link

mlevison commented May 8, 2017 via email

@sormuras
Copy link
Member Author

sormuras commented May 9, 2017

Closing this PR with comment: "Back to the design board." Follow-up at #431

@sormuras sormuras closed this May 9, 2017
@sormuras sormuras deleted the issues/48-testfactory_failfast branch January 8, 2018 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants