Bird
Raised Fist0
JUnittesting~15 mins

@Execution annotation in JUnit - Build an Automation Script

Choose your learning style10 modes available
Verify that tests run concurrently using @Execution(CONCURRENT)
Preconditions (2)
Step 1: Annotate the test class with @Execution(ExecutionMode.CONCURRENT)
Step 2: Create at least two test methods that each sleep for 2 seconds and then assert true
Step 3: Run the test class
Step 4: Observe the total execution time
✅ Expected Result: The total execution time should be close to 2 seconds, indicating tests ran concurrently
Automation Requirements - JUnit 5
Assertions Needed:
Assert that each test method completes successfully
Verify that total execution time is less than sum of individual test durations (indicating concurrency)
Best Practices:
Use @Execution annotation at class level
Use Assertions.assertTrue for simple assertions
Avoid Thread.sleep in production tests, but acceptable here for demonstration
Use System.nanoTime() or System.currentTimeMillis() to measure execution time
Automated Solution
JUnit
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Execution(ExecutionMode.CONCURRENT)
public class ConcurrentExecutionTest {

    @Test
    void testOne() throws InterruptedException {
        Thread.sleep(2000);
        assertTrue(true);
    }

    @Test
    void testTwo() throws InterruptedException {
        Thread.sleep(2000);
        assertTrue(true);
    }

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        org.junit.platform.launcher.LauncherDiscoveryRequest request =
            org.junit.platform.engine.discovery.DiscoverySelectors.selectClass(ConcurrentExecutionTest.class);

        org.junit.platform.launcher.Launcher launcher = org.junit.platform.launcher.LauncherFactory.create();
        launcher.execute(
            org.junit.platform.launcher.LauncherDiscoveryRequestBuilder.request()
                .selectors(org.junit.platform.engine.discovery.DiscoverySelectors.selectClass(ConcurrentExecutionTest.class))
                .build()
        );
        long end = System.currentTimeMillis();
        long duration = end - start;
        System.out.println("Total execution time (ms): " + duration);
        assertTrue(duration < 3500, "Tests did not run concurrently as expected");
    }
}

The test class ConcurrentExecutionTest is annotated with @Execution(ExecutionMode.CONCURRENT) to tell JUnit to run tests in parallel.

Two test methods each sleep for 2 seconds and then assert true to simulate work.

The main method runs the tests programmatically and measures total execution time.

If tests run sequentially, total time would be about 4000 ms (2 tests * 2 seconds each).

If tests run concurrently, total time should be close to 2000 ms.

The assertion checks that total time is less than 3500 ms to confirm concurrency.

Common Mistakes - 3 Pitfalls
{'mistake': 'Not annotating the test class or methods with @Execution annotation', 'why_bad': "JUnit will run tests sequentially by default, so concurrency won't happen", 'correct_approach': 'Add @Execution(ExecutionMode.CONCURRENT) at class or method level to enable parallel execution'}
{'mistake': 'Using Thread.sleep without handling InterruptedException', 'why_bad': 'Code will not compile or tests will fail unexpectedly', 'correct_approach': "Declare test methods with 'throws InterruptedException' or handle exception properly"}
Measuring execution time incorrectly or outside test run
Bonus Challenge

Now add three test methods with different sleep durations and verify that total execution time is close to the longest sleep time

Show Hint

Practice

(1/5)
1. What is the main purpose of the @Execution annotation in JUnit?
easy
A. To set the timeout for a test
B. To specify the order of test execution
C. To mark a test as disabled
D. To control whether tests run concurrently or sequentially

Solution

  1. Step 1: Understand the role of @Execution

    The @Execution annotation controls how tests are run: either all at once (concurrently) or one after another (sequentially).
  2. Step 2: Differentiate from other annotations

    It does not set order, disable tests, or set timeouts. Those are handled by other annotations like @Order, @Disabled, or @Timeout.
  3. Final Answer:

    To control whether tests run concurrently or sequentially -> Option D
  4. Quick Check:

    @Execution controls test concurrency = A [OK]
Hint: Remember: @Execution decides parallel or one-by-one run [OK]
Common Mistakes:
  • Confusing @Execution with @Order
  • Thinking it disables tests
  • Assuming it sets test timeouts
2. Which of the following is the correct syntax to run tests concurrently using @Execution in JUnit?
easy
A. @Execution(ExecutionMode.CONCURRENT)
B. @Execution(ExecutionMode.SAME_THREAD)
C. @Execution(ExecutionMode.SEQUENTIAL)
D. @Execution(ExecutionMode.PARALLEL)

Solution

  1. Step 1: Recall valid ExecutionMode values

    JUnit defines ExecutionMode.CONCURRENT and ExecutionMode.SAME_THREAD. There is no SEQUENTIAL or PARALLEL mode.
  2. Step 2: Identify the mode for concurrent execution

    ExecutionMode.CONCURRENT runs tests in parallel threads.
  3. Final Answer:

    @Execution(ExecutionMode.CONCURRENT) -> Option A
  4. Quick Check:

    Concurrent mode = CONCURRENT [OK]
Hint: Use ExecutionMode.CONCURRENT for parallel tests [OK]
Common Mistakes:
  • Using non-existent ExecutionMode values
  • Confusing SAME_THREAD with concurrent
  • Misspelling ExecutionMode constants
3. Given the following test class, what will be the order of test execution?
@Execution(ExecutionMode.CONCURRENT)
class SampleTest {
  @Test void testA() { System.out.println("A"); }
  @Test void testB() { System.out.println("B"); }
  @Test void testC() { System.out.println("C"); }
}
medium
A. Tests run one by one in order: A, B, C
B. Tests run concurrently; order of output is unpredictable
C. Tests run concurrently but always print in alphabetical order
D. Tests run sequentially but in reverse order: C, B, A

Solution

  1. Step 1: Understand ExecutionMode.CONCURRENT effect

    With @Execution(ExecutionMode.CONCURRENT), tests run in parallel threads, so their output order is not guaranteed.
  2. Step 2: Analyze output behavior

    Since threads run independently, print statements may appear in any order depending on thread scheduling.
  3. Final Answer:

    Tests run concurrently; order of output is unpredictable -> Option B
  4. Quick Check:

    Concurrent = unpredictable order [OK]
Hint: Concurrent tests print in any order, not fixed [OK]
Common Mistakes:
  • Assuming concurrent means ordered
  • Thinking output is alphabetical
  • Confusing concurrent with sequential execution
4. Identify the error in this JUnit test class using @Execution:
@Execution(ExecutionMode.CONCURRENT)
class TestExample {
  private int counter = 0;

  @Test
  void increment() {
    counter++;
    assertEquals(1, counter);
  }

  @Test
  void decrement() {
    counter--;
    assertEquals(-1, counter);
  }
}
medium
A. Shared mutable state causes race conditions in concurrent tests
B. Missing @BeforeEach to reset counter before each test
C. No error; tests run correctly in concurrent mode
D. Incorrect use of @Execution; should be @Order

Solution

  1. Step 1: Analyze shared state usage

    The counter variable is shared and modified by both tests without synchronization.
  2. Step 2: Understand concurrency impact

    Running tests concurrently causes race conditions, leading to unpredictable counter values and test failures.
  3. Final Answer:

    Shared mutable state causes race conditions in concurrent tests -> Option A
  4. Quick Check:

    Concurrent tests + shared state = race condition [OK]
Hint: Avoid shared mutable state in concurrent tests [OK]
Common Mistakes:
  • Ignoring thread safety in concurrent tests
  • Assuming tests run sequentially by default
  • Confusing @Execution with @Order annotation
5. You have a test suite with some tests that modify shared data and others that do not. How can you use @Execution to optimize test speed while avoiding conflicts?
hard
A. Remove @Execution annotations and rely on default sequential execution
B. Annotate all tests with @Execution(ExecutionMode.CONCURRENT) to run all in parallel
C. Annotate tests that modify shared data with @Execution(ExecutionMode.SAME_THREAD) and others with CONCURRENT
D. Use @Execution(ExecutionMode.SAME_THREAD) on all tests to avoid conflicts

Solution

  1. Step 1: Identify tests with shared data modification

    Tests that modify shared data must run sequentially to avoid conflicts.
  2. Step 2: Apply @Execution selectively

    Use @Execution(ExecutionMode.SAME_THREAD) on tests with shared data, and CONCURRENT on others to speed up execution.
  3. Final Answer:

    Annotate tests that modify shared data with @Execution(ExecutionMode.SAME_THREAD) and others with CONCURRENT -> Option C
  4. Quick Check:

    Mix SAME_THREAD for shared data, CONCURRENT for others [OK]
Hint: Use SAME_THREAD for shared data tests, CONCURRENT for safe ones [OK]
Common Mistakes:
  • Running all tests concurrently ignoring shared data
  • Running all tests sequentially losing speed benefits
  • Not using @Execution selectively per test
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard