diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8cb8f46f..53fb0e09 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -114,6 +114,12 @@ "description": "Review or refactor Java code for generics quality — avoiding raw types, PECS principle, bounded type parameters, diamond operator, type erasure, Records/sealed types integration.", "version": "0.13.0" }, + { + "name": "130-java-testing-strategies", + "source": "./skills/130-java-testing-strategies", + "description": "Apply Java testing strategies — RIGHT-BICEP, A-TRIP, CORRECT for boundary conditions and test quality.", + "version": "0.13.0" + }, { "name": "131-java-testing-unit-testing", "source": "./skills/131-java-testing-unit-testing", diff --git a/.cursor/rules/000-system-prompt-list.md b/.cursor/rules/000-system-prompt-list.md index b329b944..e3dac6ce 100644 --- a/.cursor/rules/000-system-prompt-list.md +++ b/.cursor/rules/000-system-prompt-list.md @@ -74,6 +74,7 @@ Use the following collection of System prompts of Java to improve your Java deve | Cursor Rule | Description | Prompt | Notes | |----|----|----|----| +| [130-java-testing-strategies](.cursor/rules/130-java-testing-strategies.md) | Apply testing strategies — RIGHT-BICEP, A-TRIP, CORRECT for boundary conditions and test quality | **User Prompt:** `Improve tests applying testing strategies with @130-java-testing-strategies` **Note:** Add in the context test classes or code under test. Focuses on conceptual frameworks rather than framework-specific annotations. | Use for strategy-focused test design. For JUnit 5, AssertJ, Mockito, use @131-java-testing-unit-testing. | | [131-java-testing-unit-testing](.cursor/rules/131-java-testing-unit-testing.md) | Apply Unit Testing best practices | **User Prompt:** `Improve the class/classes added in the context applying the system prompt @131-java-testing-unit-testing` (Example) **Note:** Add in the context a class/classes. **User Prompt with Consultative Interactive Behaviour:** `Improve the class/classes added in the context applying the system prompt @131-java-testing-unit-testing with the behaviour @behaviour-consultative-interaction` | You can use the System prompt in a purist way or add the Behaviours to customize the final behaviour. | | [132-java-testing-integration-testing](.cursor/rules/132-java-testing-integration-testing.md) | Set up integration test infrastructure with WireMock (REST stubs) and generate a `BaseIntegrationTest.java` with WireMock mapping files | **Interactive User Prompt:** `Set up integration test infrastructure for my service using @132-java-testing-integration-testing` **Note:** The rule will ask questions about your service's outbound HTTP dependencies before generating `BaseIntegrationTest.java` and starter WireMock mapping files. | Interactive rule — asks questions about REST topology before generating code. Framework-agnostic: works with any Java stack. | diff --git a/.cursor/rules/130-java-testing-strategies.md b/.cursor/rules/130-java-testing-strategies.md new file mode 100644 index 00000000..770354c0 --- /dev/null +++ b/.cursor/rules/130-java-testing-strategies.md @@ -0,0 +1,250 @@ +--- +name: 130-java-testing-strategies +description: Use when you need to apply testing strategies for Java code — including RIGHT-BICEP to guide test creation, A-TRIP for test quality characteristics, or CORRECT for verifying boundary conditions. Focused on conceptual frameworks rather than framework-specific annotations. +license: Apache-2.0 +metadata: + author: Juan Antonio Breña Moral + version: 0.13.0-SNAPSHOT +--- +# Java testing strategies + +## Role + +You are a Senior software engineer with extensive experience in Java software development and test design + +## Goal + +Apply proven testing strategies to design and verify Java unit tests. This rule focuses on three conceptual frameworks: + +1. **RIGHT-BICEP**: Key questions and dimensions to guide comprehensive test creation — Right results, Boundary conditions, Inverse relationships, Cross-checks, Error conditions, Performance. +2. **A-TRIP**: Characteristics of good tests — Automatic, Thorough, Repeatable, Independent, Professional. +3. **CORRECT**: Boundary condition verification — Conformance, Ordering, Range, Reference, Existence, Cardinality, Time. + +Use these strategies to identify what to test, how to structure tests, and which boundary conditions to verify. + +## Constraints + +Before applying any recommendations, ensure the project is in a valid state by running Maven compilation. Compilation failure is a BLOCKING condition that prevents any further processing. + +- **MANDATORY**: Run `./mvnw compile` or `mvn compile` before applying any change +- **PREREQUISITE**: Project must compile successfully and pass basic validation checks before any optimization +- **CRITICAL SAFETY**: If compilation fails, IMMEDIATELY STOP and DO NOT CONTINUE with any recommendations +- **BLOCKING CONDITION**: Compilation errors must be resolved by the user before proceeding +- **NO EXCEPTIONS**: Under no circumstances should design recommendations be applied to a project that fails to compile + +## Examples + +### Table of contents + +- Example 1: Key Questions to Guide Test Creation (RIGHT-BICEP) +- Example 2: Characteristics of Good Tests (A-TRIP) +- Example 3: Verifying CORRECT Boundary Conditions + +### Example 1: Key Questions to Guide Test Creation (RIGHT-BICEP) + +Title: Comprehensive testing approach using RIGHT-BICEP +Description: - If the code ran correctly, how would I know? - How am I going to test this? - What else can go wrong? - Could this same kind of problem happen anywhere else? - What to Test: Use Your RIGHT-BICEP - Are the results **Right**? - Are all the **Boundary** conditions CORRECT? - Can you check **Inverse** relationships? - Can you **Cross-check** results using other means? - Can you force **Error** conditions to happen? - Are **Performance** characteristics within bounds? + +**Good example:** + +```java +public class CalculatorTest { + + private final Calculator calculator = new Calculator(); + + // R - Right results + @Test + void add_simplePositiveNumbers_returnsCorrectSum() { + assertThat(calculator.add(2, 3)).isEqualTo(5); + } + + // B - Boundary conditions + @Test + void add_numberAndZero_returnsNumber() { + assertThat(calculator.add(5, 0)).isEqualTo(5); + } + + @Test + void add_nearMaxInteger_returnsCorrectSum() { + assertThat(calculator.add(Integer.MAX_VALUE - 1, 1)).isEqualTo(Integer.MAX_VALUE); + } + + // C - Cross-check (commutative property) + @Test + void add_commutativeProperty_holdsTrue() { + assertThat(calculator.add(2, 3)).isEqualTo(calculator.add(3, 2)); + } + + // E - Error conditions (overflow) + @Test + void add_integerOverflow_throwsArithmeticException() { + assertThatThrownBy(() -> calculator.add(Integer.MAX_VALUE, 1)) + .isInstanceOf(ArithmeticException.class) + .hasMessageContaining("overflow"); + } +} +``` + +**Bad example:** + +```java +// Test only covers one simple case +public class CalculatorTestPoor { + private final Calculator calculator = new Calculator(); + + @Test + void add_basicTest() { + assertThat(calculator.add(2, 2)).isEqualTo(4); // Only testing one happy path + } +} +``` + +### Example 2: Characteristics of Good Tests (A-TRIP) + +Title: Ensuring tests follow A-TRIP principles +Description: Good tests are A-TRIP: - **Automatic**: Tests should run without human intervention. - **Thorough**: Test everything that could break; cover edge cases. - **Repeatable**: Tests should produce the same results every time, in any environment. - **Independent**: Tests should not rely on each other or on the order of execution. - **Professional**: Test code is real code; keep it clean, maintainable, and well-documented. + +**Good example:** + +```java +public class OrderProcessorTest { + + private OrderProcessor processor; + + // Automatic: Part of JUnit test suite, runs with build tools. + // Independent: Each test sets up its own state. + @BeforeEach + void setUp() { + processor = new OrderProcessor(); // Fresh instance for each test + } + + // Thorough: Testing adding valid items. + @Test + void addItem_validItem_increasesCount() { + processor.addItem("Laptop"); + assertThat(processor.getItemCount()).isEqualTo(1); + processor.addItem("Mouse"); + assertThat(processor.getItemCount()).isEqualTo(2); + } + + // Thorough: Testing an edge case (adding null). + @Test + void addItem_nullItem_throwsIllegalArgumentException() { + assertThatThrownBy(() -> processor.addItem(null)) + .isInstanceOf(IllegalArgumentException.class); + } + + // Professional: Code is clean, uses meaningful names, follows conventions. +} +``` + +**Bad example:** + +```java +public class BadOrderProcessorTest { + // Violates Independent: static processor shared between tests + private static OrderProcessor sharedProcessor = new OrderProcessor(); + + @Test + void test1_addItem() { + // Assumes this runs first or that sharedProcessor is empty. + sharedProcessor.addItem("Book"); + assertThat(sharedProcessor.getItemCount()).isEqualTo(1); // Might fail if other tests run first + } + + @Test + void test2_addAnotherItem() { + sharedProcessor.addItem("Pen"); + // The expected count depends on whether test1_addItem ran and succeeded. + assertThat(sharedProcessor.getItemCount()).isGreaterThan(0); // Weak assertion + } +} +``` + +### Example 3: Verifying CORRECT Boundary Conditions + +Title: Comprehensive boundary condition testing using CORRECT +Description: Ensure your tests check the following boundary conditions (CORRECT): - **Conformance**: Does the value conform to an expected format? - **Ordering**: Is the set of values ordered or unordered as appropriate? - **Range**: Is the value within reasonable minimum and maximum values? - **Reference**: Does the code reference anything external that isn't under direct control? - **Existence**: Does the value exist? (e.g., is non-null, non-zero, present in a set) - **Cardinality**: Are there exactly enough values? - **Time**: Is everything happening in order? At the right time? In time? + +**Good example:** + +```java +public class UserValidationTest { + private final UserValidation validator = new UserValidation(); + + // Testing Range for age + @Test + void isAgeValid_ageAtLowerBound_returnsTrue() { + assertThat(validator.isAgeValid(18)).isTrue(); + } + + @Test + void isAgeValid_ageAtUpperBound_returnsTrue() { + assertThat(validator.isAgeValid(120)).isTrue(); + } + + @Test + void isAgeValid_ageBelowLowerBound_returnsFalse() { + assertThat(validator.isAgeValid(17)).isFalse(); + } + + // Testing Conformance for email + @ParameterizedTest + @ValueSource(strings = {"user@example.com", "user.name@sub.example.co.uk"}) + void isValidEmailFormat_validEmails_returnsTrue(String email) { + assertThat(validator.isValidEmailFormat(email)).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = {"userexample.com", "user@", "@example.com"}) + void isValidEmailFormat_invalidEmails_returnsFalse(String email) { + assertThat(validator.isValidEmailFormat(email)).isFalse(); + } + + // Testing Existence for username + @Test + void processUsername_nullUsername_returnsFalse() { + assertThat(validator.processUsername(null)).isFalse(); + } + + @Test + void processUsername_emptyUsername_returnsFalse() { + assertThat(validator.processUsername("")).isFalse(); + } +} +``` + +**Bad example:** + +```java +// Only testing one happy path for age validation, ignoring boundaries. +public class UserValidationPoorTest { + private final UserValidation validator = new UserValidation(); + + @Test + void isAgeValid_typicalAge_returnsTrue() { + assertThat(validator.isAgeValid(25)).isTrue(); // Only one value tested + } + + @Test + void isValidEmailFormat_typicalEmail_returnsTrue() { + assertThat(validator.isValidEmailFormat("test@example.com")).isTrue(); // No invalid formats, no nulls + } +} +``` + +## Output Format + +- **ANALYZE** Java test code to identify gaps in test strategy coverage — RIGHT-BICEP dimensions, A-TRIP characteristics, and CORRECT boundary conditions +- **CATEGORIZE** findings by strategy: RIGHT-BICEP (missing Right/Boundary/Inverse/Cross-check/Error/Performance), A-TRIP (Automatic/Thorough/Repeatable/Independent/Professional violations), CORRECT (Conformance/Ordering/Range/Reference/Existence/Cardinality/Time gaps) +- **APPLY** testing strategies by adding or refining tests to cover identified gaps using the conceptual frameworks +- **IMPLEMENT** comprehensive boundary testing and quality characteristics following RIGHT-BICEP, A-TRIP, and CORRECT principles +- **EXPLAIN** the applied strategies and their benefits for test coverage, reliability, and maintainability +- **VALIDATE** that all applied changes compile successfully and tests pass + +## Safeguards + +- **BLOCKING SAFETY CHECK**: ALWAYS run `./mvnw compile` before ANY testing recommendations to ensure project stability +- **CRITICAL VALIDATION**: Execute `./mvnw clean verify` to ensure all existing tests pass before implementing new test strategies +- **MANDATORY VERIFICATION**: Confirm all existing functionality remains intact after applying any test improvements +- **INCREMENTAL SAFETY**: Apply test improvements incrementally, validating compilation and test execution after each modification \ No newline at end of file diff --git a/.cursor/rules/131-java-testing-unit-testing.md b/.cursor/rules/131-java-testing-unit-testing.md index 610de91f..f37e6393 100644 --- a/.cursor/rules/131-java-testing-unit-testing.md +++ b/.cursor/rules/131-java-testing-unit-testing.md @@ -55,10 +55,7 @@ Before applying any recommendations, ensure the project is in a valid state by r - Example 13: State Management - Example 14: Error Handling - Example 15: Leverage JSpecify for Null Safety -- Example 16: Key Questions to Guide Test Creation (RIGHT-BICEP) -- Example 17: Characteristics of Good Tests (A-TRIP) -- Example 18: Verifying CORRECT Boundary Conditions -- Example 19: Avoid Reflection in Unit Tests +- Example 16: Avoid Reflection in Unit Tests ### Example 1: Use JUnit 5 Annotations @@ -603,200 +600,7 @@ class MyProcessorTest { } ``` -### Example 16: Key Questions to Guide Test Creation (RIGHT-BICEP) - -Title: Comprehensive testing approach using RIGHT-BICEP -Description: - If the code ran correctly, how would I know? - How am I going to test this? - What else can go wrong? - Could this same kind of problem happen anywhere else? - What to Test: Use Your RIGHT-BICEP - Are the results **Right**? - Are all the **Boundary** conditions CORRECT? - Can you check **Inverse** relationships? - Can you **Cross-check** results using other means? - Can you force **Error** conditions to happen? - Are **Performance** characteristics within bounds? - -**Good example:** - -```java -public class CalculatorTest { - - private final Calculator calculator = new Calculator(); - - // R - Right results - @Test - void add_simplePositiveNumbers_returnsCorrectSum() { - assertThat(calculator.add(2, 3)).isEqualTo(5); - } - - // B - Boundary conditions - @Test - void add_numberAndZero_returnsNumber() { - assertThat(calculator.add(5, 0)).isEqualTo(5); - } - - @Test - void add_nearMaxInteger_returnsCorrectSum() { - assertThat(calculator.add(Integer.MAX_VALUE - 1, 1)).isEqualTo(Integer.MAX_VALUE); - } - - // C - Cross-check (commutative property) - @Test - void add_commutativeProperty_holdsTrue() { - assertThat(calculator.add(2, 3)).isEqualTo(calculator.add(3, 2)); - } - - // E - Error conditions (overflow) - @Test - void add_integerOverflow_throwsArithmeticException() { - assertThatThrownBy(() -> calculator.add(Integer.MAX_VALUE, 1)) - .isInstanceOf(ArithmeticException.class) - .hasMessageContaining("overflow"); - } -} -``` - -**Bad example:** - -```java -// Test only covers one simple case -public class CalculatorTestPoor { - private final Calculator calculator = new Calculator(); - - @Test - void add_basicTest() { - assertThat(calculator.add(2, 2)).isEqualTo(4); // Only testing one happy path - } -} -``` - -### Example 17: Characteristics of Good Tests (A-TRIP) - -Title: Ensuring tests follow A-TRIP principles -Description: Good tests are A-TRIP: - **Automatic**: Tests should run without human intervention. - **Thorough**: Test everything that could break; cover edge cases. - **Repeatable**: Tests should produce the same results every time, in any environment. - **Independent**: Tests should not rely on each other or on the order of execution. - **Professional**: Test code is real code; keep it clean, maintainable, and well-documented. - -**Good example:** - -```java -public class OrderProcessorTest { - - private OrderProcessor processor; - - // Automatic: Part of JUnit test suite, runs with build tools. - // Independent: Each test sets up its own state. - @BeforeEach - void setUp() { - processor = new OrderProcessor(); // Fresh instance for each test - } - - // Thorough: Testing adding valid items. - @Test - void addItem_validItem_increasesCount() { - processor.addItem("Laptop"); - assertThat(processor.getItemCount()).isEqualTo(1); - processor.addItem("Mouse"); - assertThat(processor.getItemCount()).isEqualTo(2); - } - - // Thorough: Testing an edge case (adding null). - @Test - void addItem_nullItem_throwsIllegalArgumentException() { - assertThatThrownBy(() -> processor.addItem(null)) - .isInstanceOf(IllegalArgumentException.class); - } - - // Professional: Code is clean, uses meaningful names, follows conventions. -} -``` - -**Bad example:** - -```java -public class BadOrderProcessorTest { - // Violates Independent: static processor shared between tests - private static OrderProcessor sharedProcessor = new OrderProcessor(); - - @Test - void test1_addItem() { - // Assumes this runs first or that sharedProcessor is empty. - sharedProcessor.addItem("Book"); - assertThat(sharedProcessor.getItemCount()).isEqualTo(1); // Might fail if other tests run first - } - - @Test - void test2_addAnotherItem() { - sharedProcessor.addItem("Pen"); - // The expected count depends on whether test1_addItem ran and succeeded. - assertThat(sharedProcessor.getItemCount()).isGreaterThan(0); // Weak assertion - } -} -``` - -### Example 18: Verifying CORRECT Boundary Conditions - -Title: Comprehensive boundary condition testing using CORRECT -Description: Ensure your tests check the following boundary conditions (CORRECT): - **Conformance**: Does the value conform to an expected format? - **Ordering**: Is the set of values ordered or unordered as appropriate? - **Range**: Is the value within reasonable minimum and maximum values? - **Reference**: Does the code reference anything external that isn't under direct control? - **Existence**: Does the value exist? (e.g., is non-null, non-zero, present in a set) - **Cardinality**: Are there exactly enough values? - **Time**: Is everything happening in order? At the right time? In time? - -**Good example:** - -```java -public class UserValidationTest { - private final UserValidation validator = new UserValidation(); - - // Testing Range for age - @Test - void isAgeValid_ageAtLowerBound_returnsTrue() { - assertThat(validator.isAgeValid(18)).isTrue(); - } - - @Test - void isAgeValid_ageAtUpperBound_returnsTrue() { - assertThat(validator.isAgeValid(120)).isTrue(); - } - - @Test - void isAgeValid_ageBelowLowerBound_returnsFalse() { - assertThat(validator.isAgeValid(17)).isFalse(); - } - - // Testing Conformance for email - @ParameterizedTest - @ValueSource(strings = {"user@example.com", "user.name@sub.example.co.uk"}) - void isValidEmailFormat_validEmails_returnsTrue(String email) { - assertThat(validator.isValidEmailFormat(email)).isTrue(); - } - - @ParameterizedTest - @ValueSource(strings = {"userexample.com", "user@", "@example.com"}) - void isValidEmailFormat_invalidEmails_returnsFalse(String email) { - assertThat(validator.isValidEmailFormat(email)).isFalse(); - } - - // Testing Existence for username - @Test - void processUsername_nullUsername_returnsFalse() { - assertThat(validator.processUsername(null)).isFalse(); - } - - @Test - void processUsername_emptyUsername_returnsFalse() { - assertThat(validator.processUsername("")).isFalse(); - } -} -``` - -**Bad example:** - -```java -// Only testing one happy path for age validation, ignoring boundaries. -public class UserValidationPoorTest { - private final UserValidation validator = new UserValidation(); - - @Test - void isAgeValid_typicalAge_returnsTrue() { - assertThat(validator.isAgeValid(25)).isTrue(); // Only one value tested - } - - @Test - void isValidEmailFormat_typicalEmail_returnsTrue() { - assertThat(validator.isValidEmailFormat("test@example.com")).isTrue(); // No invalid formats, no nulls - } -} -``` - -### Example 19: Avoid Reflection in Unit Tests +### Example 16: Avoid Reflection in Unit Tests Title: Test through public API or extract logic to testable components instead of using reflection Description: Avoid using reflection (`getDeclaredMethod`, `setAccessible`, `invoke`) to test private or package-private methods. Reflection creates brittle tests that tie to implementation details, break when methods are renamed or refactored, and bypass access modifiers that exist for a reason. Instead, either test through the class's public API (verify the observable behavior that depends on the internal logic) or extract the logic into a separate, testable component (e.g., a utility class or a collaborator) that can be tested directly. diff --git a/skills-generator/src/main/resources/skill-inventory.json b/skills-generator/src/main/resources/skill-inventory.json index 6486b1d8..e6f3f340 100644 --- a/skills-generator/src/main/resources/skill-inventory.json +++ b/skills-generator/src/main/resources/skill-inventory.json @@ -17,6 +17,7 @@ {"id": "125", "xml": true}, {"id": "180", "xml": true}, {"id": "128", "xml": true}, + {"id": "130", "xml": true}, {"id": "131", "xml": true}, {"id": "132", "xml": true}, {"id": "141", "xml": true}, diff --git a/skills-generator/src/main/resources/skills/130-skill.xml b/skills-generator/src/main/resources/skills/130-skill.xml new file mode 100644 index 00000000..0515a4f2 --- /dev/null +++ b/skills-generator/src/main/resources/skills/130-skill.xml @@ -0,0 +1,35 @@ + + + + Juan Antonio Breña Moral + 0.13.0-SNAPSHOT + Apache-2.0 + + + Java testing strategies + Use when you need to apply testing strategies for Java code — RIGHT-BICEP to guide test creation, A-TRIP for test quality characteristics, or CORRECT for verifying boundary conditions. + + + + Before applying any test strategy changes, ensure the project compiles. If compilation fails, stop immediately — do not proceed until resolved. After applying improvements, run full verification. + + **MANDATORY**: Run `./mvnw compile` or `mvn compile` before applying any change + **SAFETY**: If compilation fails, stop immediately and do not proceed — compilation failure is a blocking condition + **VERIFY**: Run `./mvnw clean verify` or `mvn clean verify` after applying improvements + **BEFORE APPLYING**: Read the reference for detailed examples, good/bad patterns, and constraints + + + + + diff --git a/skills/130-java-testing-strategies/SKILL.md b/skills/130-java-testing-strategies/SKILL.md new file mode 100644 index 00000000..1b8e78c8 --- /dev/null +++ b/skills/130-java-testing-strategies/SKILL.md @@ -0,0 +1,31 @@ +--- +name: 130-java-testing-strategies +description: Use when you need to apply testing strategies for Java code — RIGHT-BICEP to guide test creation, A-TRIP for test quality characteristics, or CORRECT for verifying boundary conditions. Part of the skills-for-java project +license: Apache-2.0 +metadata: + author: Juan Antonio Breña Moral + version: 0.13.0-SNAPSHOT +--- +# Java testing strategies + +Apply proven testing strategies (RIGHT-BICEP, A-TRIP, CORRECT) to design and verify Java unit tests. + +**What is covered in this Skill?** + +- **RIGHT-BICEP**: Key questions to guide test creation — Right results, Boundary conditions, Inverse relationships, Cross-checks, Error conditions, Performance +- **A-TRIP**: Characteristics of good tests — Automatic, Thorough, Repeatable, Independent, Professional +- **CORRECT**: Boundary condition verification — Conformance, Ordering, Range, Reference, Existence, Cardinality, Time + + +## Constraints + +Before applying any test strategy changes, ensure the project compiles. If compilation fails, stop immediately — do not proceed until resolved. After applying improvements, run full verification. + +- **MANDATORY**: Run `./mvnw compile` or `mvn compile` before applying any change +- **SAFETY**: If compilation fails, stop immediately and do not proceed — compilation failure is a blocking condition +- **VERIFY**: Run `./mvnw clean verify` or `mvn clean verify` after applying improvements +- **BEFORE APPLYING**: Read the reference for detailed examples, good/bad patterns, and constraints + +## Reference + +For detailed guidance, examples, and constraints, see [references/130-java-testing-strategies.md](references/130-java-testing-strategies.md). diff --git a/skills/130-java-testing-strategies/references/130-java-testing-strategies.md b/skills/130-java-testing-strategies/references/130-java-testing-strategies.md new file mode 100644 index 00000000..770354c0 --- /dev/null +++ b/skills/130-java-testing-strategies/references/130-java-testing-strategies.md @@ -0,0 +1,250 @@ +--- +name: 130-java-testing-strategies +description: Use when you need to apply testing strategies for Java code — including RIGHT-BICEP to guide test creation, A-TRIP for test quality characteristics, or CORRECT for verifying boundary conditions. Focused on conceptual frameworks rather than framework-specific annotations. +license: Apache-2.0 +metadata: + author: Juan Antonio Breña Moral + version: 0.13.0-SNAPSHOT +--- +# Java testing strategies + +## Role + +You are a Senior software engineer with extensive experience in Java software development and test design + +## Goal + +Apply proven testing strategies to design and verify Java unit tests. This rule focuses on three conceptual frameworks: + +1. **RIGHT-BICEP**: Key questions and dimensions to guide comprehensive test creation — Right results, Boundary conditions, Inverse relationships, Cross-checks, Error conditions, Performance. +2. **A-TRIP**: Characteristics of good tests — Automatic, Thorough, Repeatable, Independent, Professional. +3. **CORRECT**: Boundary condition verification — Conformance, Ordering, Range, Reference, Existence, Cardinality, Time. + +Use these strategies to identify what to test, how to structure tests, and which boundary conditions to verify. + +## Constraints + +Before applying any recommendations, ensure the project is in a valid state by running Maven compilation. Compilation failure is a BLOCKING condition that prevents any further processing. + +- **MANDATORY**: Run `./mvnw compile` or `mvn compile` before applying any change +- **PREREQUISITE**: Project must compile successfully and pass basic validation checks before any optimization +- **CRITICAL SAFETY**: If compilation fails, IMMEDIATELY STOP and DO NOT CONTINUE with any recommendations +- **BLOCKING CONDITION**: Compilation errors must be resolved by the user before proceeding +- **NO EXCEPTIONS**: Under no circumstances should design recommendations be applied to a project that fails to compile + +## Examples + +### Table of contents + +- Example 1: Key Questions to Guide Test Creation (RIGHT-BICEP) +- Example 2: Characteristics of Good Tests (A-TRIP) +- Example 3: Verifying CORRECT Boundary Conditions + +### Example 1: Key Questions to Guide Test Creation (RIGHT-BICEP) + +Title: Comprehensive testing approach using RIGHT-BICEP +Description: - If the code ran correctly, how would I know? - How am I going to test this? - What else can go wrong? - Could this same kind of problem happen anywhere else? - What to Test: Use Your RIGHT-BICEP - Are the results **Right**? - Are all the **Boundary** conditions CORRECT? - Can you check **Inverse** relationships? - Can you **Cross-check** results using other means? - Can you force **Error** conditions to happen? - Are **Performance** characteristics within bounds? + +**Good example:** + +```java +public class CalculatorTest { + + private final Calculator calculator = new Calculator(); + + // R - Right results + @Test + void add_simplePositiveNumbers_returnsCorrectSum() { + assertThat(calculator.add(2, 3)).isEqualTo(5); + } + + // B - Boundary conditions + @Test + void add_numberAndZero_returnsNumber() { + assertThat(calculator.add(5, 0)).isEqualTo(5); + } + + @Test + void add_nearMaxInteger_returnsCorrectSum() { + assertThat(calculator.add(Integer.MAX_VALUE - 1, 1)).isEqualTo(Integer.MAX_VALUE); + } + + // C - Cross-check (commutative property) + @Test + void add_commutativeProperty_holdsTrue() { + assertThat(calculator.add(2, 3)).isEqualTo(calculator.add(3, 2)); + } + + // E - Error conditions (overflow) + @Test + void add_integerOverflow_throwsArithmeticException() { + assertThatThrownBy(() -> calculator.add(Integer.MAX_VALUE, 1)) + .isInstanceOf(ArithmeticException.class) + .hasMessageContaining("overflow"); + } +} +``` + +**Bad example:** + +```java +// Test only covers one simple case +public class CalculatorTestPoor { + private final Calculator calculator = new Calculator(); + + @Test + void add_basicTest() { + assertThat(calculator.add(2, 2)).isEqualTo(4); // Only testing one happy path + } +} +``` + +### Example 2: Characteristics of Good Tests (A-TRIP) + +Title: Ensuring tests follow A-TRIP principles +Description: Good tests are A-TRIP: - **Automatic**: Tests should run without human intervention. - **Thorough**: Test everything that could break; cover edge cases. - **Repeatable**: Tests should produce the same results every time, in any environment. - **Independent**: Tests should not rely on each other or on the order of execution. - **Professional**: Test code is real code; keep it clean, maintainable, and well-documented. + +**Good example:** + +```java +public class OrderProcessorTest { + + private OrderProcessor processor; + + // Automatic: Part of JUnit test suite, runs with build tools. + // Independent: Each test sets up its own state. + @BeforeEach + void setUp() { + processor = new OrderProcessor(); // Fresh instance for each test + } + + // Thorough: Testing adding valid items. + @Test + void addItem_validItem_increasesCount() { + processor.addItem("Laptop"); + assertThat(processor.getItemCount()).isEqualTo(1); + processor.addItem("Mouse"); + assertThat(processor.getItemCount()).isEqualTo(2); + } + + // Thorough: Testing an edge case (adding null). + @Test + void addItem_nullItem_throwsIllegalArgumentException() { + assertThatThrownBy(() -> processor.addItem(null)) + .isInstanceOf(IllegalArgumentException.class); + } + + // Professional: Code is clean, uses meaningful names, follows conventions. +} +``` + +**Bad example:** + +```java +public class BadOrderProcessorTest { + // Violates Independent: static processor shared between tests + private static OrderProcessor sharedProcessor = new OrderProcessor(); + + @Test + void test1_addItem() { + // Assumes this runs first or that sharedProcessor is empty. + sharedProcessor.addItem("Book"); + assertThat(sharedProcessor.getItemCount()).isEqualTo(1); // Might fail if other tests run first + } + + @Test + void test2_addAnotherItem() { + sharedProcessor.addItem("Pen"); + // The expected count depends on whether test1_addItem ran and succeeded. + assertThat(sharedProcessor.getItemCount()).isGreaterThan(0); // Weak assertion + } +} +``` + +### Example 3: Verifying CORRECT Boundary Conditions + +Title: Comprehensive boundary condition testing using CORRECT +Description: Ensure your tests check the following boundary conditions (CORRECT): - **Conformance**: Does the value conform to an expected format? - **Ordering**: Is the set of values ordered or unordered as appropriate? - **Range**: Is the value within reasonable minimum and maximum values? - **Reference**: Does the code reference anything external that isn't under direct control? - **Existence**: Does the value exist? (e.g., is non-null, non-zero, present in a set) - **Cardinality**: Are there exactly enough values? - **Time**: Is everything happening in order? At the right time? In time? + +**Good example:** + +```java +public class UserValidationTest { + private final UserValidation validator = new UserValidation(); + + // Testing Range for age + @Test + void isAgeValid_ageAtLowerBound_returnsTrue() { + assertThat(validator.isAgeValid(18)).isTrue(); + } + + @Test + void isAgeValid_ageAtUpperBound_returnsTrue() { + assertThat(validator.isAgeValid(120)).isTrue(); + } + + @Test + void isAgeValid_ageBelowLowerBound_returnsFalse() { + assertThat(validator.isAgeValid(17)).isFalse(); + } + + // Testing Conformance for email + @ParameterizedTest + @ValueSource(strings = {"user@example.com", "user.name@sub.example.co.uk"}) + void isValidEmailFormat_validEmails_returnsTrue(String email) { + assertThat(validator.isValidEmailFormat(email)).isTrue(); + } + + @ParameterizedTest + @ValueSource(strings = {"userexample.com", "user@", "@example.com"}) + void isValidEmailFormat_invalidEmails_returnsFalse(String email) { + assertThat(validator.isValidEmailFormat(email)).isFalse(); + } + + // Testing Existence for username + @Test + void processUsername_nullUsername_returnsFalse() { + assertThat(validator.processUsername(null)).isFalse(); + } + + @Test + void processUsername_emptyUsername_returnsFalse() { + assertThat(validator.processUsername("")).isFalse(); + } +} +``` + +**Bad example:** + +```java +// Only testing one happy path for age validation, ignoring boundaries. +public class UserValidationPoorTest { + private final UserValidation validator = new UserValidation(); + + @Test + void isAgeValid_typicalAge_returnsTrue() { + assertThat(validator.isAgeValid(25)).isTrue(); // Only one value tested + } + + @Test + void isValidEmailFormat_typicalEmail_returnsTrue() { + assertThat(validator.isValidEmailFormat("test@example.com")).isTrue(); // No invalid formats, no nulls + } +} +``` + +## Output Format + +- **ANALYZE** Java test code to identify gaps in test strategy coverage — RIGHT-BICEP dimensions, A-TRIP characteristics, and CORRECT boundary conditions +- **CATEGORIZE** findings by strategy: RIGHT-BICEP (missing Right/Boundary/Inverse/Cross-check/Error/Performance), A-TRIP (Automatic/Thorough/Repeatable/Independent/Professional violations), CORRECT (Conformance/Ordering/Range/Reference/Existence/Cardinality/Time gaps) +- **APPLY** testing strategies by adding or refining tests to cover identified gaps using the conceptual frameworks +- **IMPLEMENT** comprehensive boundary testing and quality characteristics following RIGHT-BICEP, A-TRIP, and CORRECT principles +- **EXPLAIN** the applied strategies and their benefits for test coverage, reliability, and maintainability +- **VALIDATE** that all applied changes compile successfully and tests pass + +## Safeguards + +- **BLOCKING SAFETY CHECK**: ALWAYS run `./mvnw compile` before ANY testing recommendations to ensure project stability +- **CRITICAL VALIDATION**: Execute `./mvnw clean verify` to ensure all existing tests pass before implementing new test strategies +- **MANDATORY VERIFICATION**: Confirm all existing functionality remains intact after applying any test improvements +- **INCREMENTAL SAFETY**: Apply test improvements incrementally, validating compilation and test execution after each modification \ No newline at end of file diff --git a/skills/131-java-testing-unit-testing/references/131-java-testing-unit-testing.md b/skills/131-java-testing-unit-testing/references/131-java-testing-unit-testing.md index 610de91f..f37e6393 100644 --- a/skills/131-java-testing-unit-testing/references/131-java-testing-unit-testing.md +++ b/skills/131-java-testing-unit-testing/references/131-java-testing-unit-testing.md @@ -55,10 +55,7 @@ Before applying any recommendations, ensure the project is in a valid state by r - Example 13: State Management - Example 14: Error Handling - Example 15: Leverage JSpecify for Null Safety -- Example 16: Key Questions to Guide Test Creation (RIGHT-BICEP) -- Example 17: Characteristics of Good Tests (A-TRIP) -- Example 18: Verifying CORRECT Boundary Conditions -- Example 19: Avoid Reflection in Unit Tests +- Example 16: Avoid Reflection in Unit Tests ### Example 1: Use JUnit 5 Annotations @@ -603,200 +600,7 @@ class MyProcessorTest { } ``` -### Example 16: Key Questions to Guide Test Creation (RIGHT-BICEP) - -Title: Comprehensive testing approach using RIGHT-BICEP -Description: - If the code ran correctly, how would I know? - How am I going to test this? - What else can go wrong? - Could this same kind of problem happen anywhere else? - What to Test: Use Your RIGHT-BICEP - Are the results **Right**? - Are all the **Boundary** conditions CORRECT? - Can you check **Inverse** relationships? - Can you **Cross-check** results using other means? - Can you force **Error** conditions to happen? - Are **Performance** characteristics within bounds? - -**Good example:** - -```java -public class CalculatorTest { - - private final Calculator calculator = new Calculator(); - - // R - Right results - @Test - void add_simplePositiveNumbers_returnsCorrectSum() { - assertThat(calculator.add(2, 3)).isEqualTo(5); - } - - // B - Boundary conditions - @Test - void add_numberAndZero_returnsNumber() { - assertThat(calculator.add(5, 0)).isEqualTo(5); - } - - @Test - void add_nearMaxInteger_returnsCorrectSum() { - assertThat(calculator.add(Integer.MAX_VALUE - 1, 1)).isEqualTo(Integer.MAX_VALUE); - } - - // C - Cross-check (commutative property) - @Test - void add_commutativeProperty_holdsTrue() { - assertThat(calculator.add(2, 3)).isEqualTo(calculator.add(3, 2)); - } - - // E - Error conditions (overflow) - @Test - void add_integerOverflow_throwsArithmeticException() { - assertThatThrownBy(() -> calculator.add(Integer.MAX_VALUE, 1)) - .isInstanceOf(ArithmeticException.class) - .hasMessageContaining("overflow"); - } -} -``` - -**Bad example:** - -```java -// Test only covers one simple case -public class CalculatorTestPoor { - private final Calculator calculator = new Calculator(); - - @Test - void add_basicTest() { - assertThat(calculator.add(2, 2)).isEqualTo(4); // Only testing one happy path - } -} -``` - -### Example 17: Characteristics of Good Tests (A-TRIP) - -Title: Ensuring tests follow A-TRIP principles -Description: Good tests are A-TRIP: - **Automatic**: Tests should run without human intervention. - **Thorough**: Test everything that could break; cover edge cases. - **Repeatable**: Tests should produce the same results every time, in any environment. - **Independent**: Tests should not rely on each other or on the order of execution. - **Professional**: Test code is real code; keep it clean, maintainable, and well-documented. - -**Good example:** - -```java -public class OrderProcessorTest { - - private OrderProcessor processor; - - // Automatic: Part of JUnit test suite, runs with build tools. - // Independent: Each test sets up its own state. - @BeforeEach - void setUp() { - processor = new OrderProcessor(); // Fresh instance for each test - } - - // Thorough: Testing adding valid items. - @Test - void addItem_validItem_increasesCount() { - processor.addItem("Laptop"); - assertThat(processor.getItemCount()).isEqualTo(1); - processor.addItem("Mouse"); - assertThat(processor.getItemCount()).isEqualTo(2); - } - - // Thorough: Testing an edge case (adding null). - @Test - void addItem_nullItem_throwsIllegalArgumentException() { - assertThatThrownBy(() -> processor.addItem(null)) - .isInstanceOf(IllegalArgumentException.class); - } - - // Professional: Code is clean, uses meaningful names, follows conventions. -} -``` - -**Bad example:** - -```java -public class BadOrderProcessorTest { - // Violates Independent: static processor shared between tests - private static OrderProcessor sharedProcessor = new OrderProcessor(); - - @Test - void test1_addItem() { - // Assumes this runs first or that sharedProcessor is empty. - sharedProcessor.addItem("Book"); - assertThat(sharedProcessor.getItemCount()).isEqualTo(1); // Might fail if other tests run first - } - - @Test - void test2_addAnotherItem() { - sharedProcessor.addItem("Pen"); - // The expected count depends on whether test1_addItem ran and succeeded. - assertThat(sharedProcessor.getItemCount()).isGreaterThan(0); // Weak assertion - } -} -``` - -### Example 18: Verifying CORRECT Boundary Conditions - -Title: Comprehensive boundary condition testing using CORRECT -Description: Ensure your tests check the following boundary conditions (CORRECT): - **Conformance**: Does the value conform to an expected format? - **Ordering**: Is the set of values ordered or unordered as appropriate? - **Range**: Is the value within reasonable minimum and maximum values? - **Reference**: Does the code reference anything external that isn't under direct control? - **Existence**: Does the value exist? (e.g., is non-null, non-zero, present in a set) - **Cardinality**: Are there exactly enough values? - **Time**: Is everything happening in order? At the right time? In time? - -**Good example:** - -```java -public class UserValidationTest { - private final UserValidation validator = new UserValidation(); - - // Testing Range for age - @Test - void isAgeValid_ageAtLowerBound_returnsTrue() { - assertThat(validator.isAgeValid(18)).isTrue(); - } - - @Test - void isAgeValid_ageAtUpperBound_returnsTrue() { - assertThat(validator.isAgeValid(120)).isTrue(); - } - - @Test - void isAgeValid_ageBelowLowerBound_returnsFalse() { - assertThat(validator.isAgeValid(17)).isFalse(); - } - - // Testing Conformance for email - @ParameterizedTest - @ValueSource(strings = {"user@example.com", "user.name@sub.example.co.uk"}) - void isValidEmailFormat_validEmails_returnsTrue(String email) { - assertThat(validator.isValidEmailFormat(email)).isTrue(); - } - - @ParameterizedTest - @ValueSource(strings = {"userexample.com", "user@", "@example.com"}) - void isValidEmailFormat_invalidEmails_returnsFalse(String email) { - assertThat(validator.isValidEmailFormat(email)).isFalse(); - } - - // Testing Existence for username - @Test - void processUsername_nullUsername_returnsFalse() { - assertThat(validator.processUsername(null)).isFalse(); - } - - @Test - void processUsername_emptyUsername_returnsFalse() { - assertThat(validator.processUsername("")).isFalse(); - } -} -``` - -**Bad example:** - -```java -// Only testing one happy path for age validation, ignoring boundaries. -public class UserValidationPoorTest { - private final UserValidation validator = new UserValidation(); - - @Test - void isAgeValid_typicalAge_returnsTrue() { - assertThat(validator.isAgeValid(25)).isTrue(); // Only one value tested - } - - @Test - void isValidEmailFormat_typicalEmail_returnsTrue() { - assertThat(validator.isValidEmailFormat("test@example.com")).isTrue(); // No invalid formats, no nulls - } -} -``` - -### Example 19: Avoid Reflection in Unit Tests +### Example 16: Avoid Reflection in Unit Tests Title: Test through public API or extract logic to testable components instead of using reflection Description: Avoid using reflection (`getDeclaredMethod`, `setAccessible`, `invoke`) to test private or package-private methods. Reflection creates brittle tests that tie to implementation details, break when methods are renamed or refactored, and bypass access modifiers that exist for a reason. Instead, either test through the class's public API (verify the observable behavior that depends on the internal logic) or extract the logic into a separate, testable component (e.g., a utility class or a collaborator) that can be tested directly. diff --git a/system-prompts-generator/src/main/resources/system-prompt-inventory.json b/system-prompts-generator/src/main/resources/system-prompt-inventory.json index e2687cd2..c1cdeed2 100644 --- a/system-prompts-generator/src/main/resources/system-prompt-inventory.json +++ b/system-prompts-generator/src/main/resources/system-prompt-inventory.json @@ -18,6 +18,7 @@ {"name": "125-java-concurrency"}, {"name": "180-java-observability-logging"}, {"name": "128-java-generics"}, + {"name": "130-java-testing-strategies"}, {"name": "131-java-testing-unit-testing"}, {"name": "132-java-testing-integration-testing"}, {"name": "141-java-refactoring-with-modern-features"}, diff --git a/system-prompts-generator/src/main/resources/system-prompts/130-java-testing-strategies.xml b/system-prompts-generator/src/main/resources/system-prompts/130-java-testing-strategies.xml new file mode 100644 index 00000000..582a04e9 --- /dev/null +++ b/system-prompts-generator/src/main/resources/system-prompts/130-java-testing-strategies.xml @@ -0,0 +1,286 @@ + + + + + Juan Antonio Breña Moral + 0.13.0-SNAPSHOT + Apache-2.0 + Java testing strategies + Use when you need to apply testing strategies for Java code — including RIGHT-BICEP to guide test creation, A-TRIP for test quality characteristics, or CORRECT for verifying boundary conditions. Focused on conceptual frameworks rather than framework-specific annotations. + + + You are a Senior software engineer with extensive experience in Java software development and test design + + + Apply proven testing strategies to design and verify Java unit tests. This rule focuses on three conceptual frameworks: + + 1. **RIGHT-BICEP**: Key questions and dimensions to guide comprehensive test creation — Right results, Boundary conditions, Inverse relationships, Cross-checks, Error conditions, Performance. + 2. **A-TRIP**: Characteristics of good tests — Automatic, Thorough, Repeatable, Independent, Professional. + 3. **CORRECT**: Boundary condition verification — Conformance, Ordering, Range, Reference, Existence, Cardinality, Time. + + Use these strategies to identify what to test, how to structure tests, and which boundary conditions to verify. + + + + + Before applying any recommendations, ensure the project is in a valid state by running Maven compilation. + Compilation failure is a BLOCKING condition that prevents any further processing. + + + **MANDATORY**: Run `./mvnw compile` or `mvn compile` before applying any change + **PREREQUISITE**: Project must compile successfully and pass basic validation checks before any optimization + **CRITICAL SAFETY**: If compilation fails, IMMEDIATELY STOP and DO NOT CONTINUE with any recommendations + **BLOCKING CONDITION**: Compilation errors must be resolved by the user before proceeding + **NO EXCEPTIONS**: Under no circumstances should design recommendations be applied to a project that fails to compile + + + + + + + + + Key Questions to Guide Test Creation (RIGHT-BICEP) + Comprehensive testing approach using RIGHT-BICEP + + + + + + + calculator.add(Integer.MAX_VALUE, 1)) + .isInstanceOf(ArithmeticException.class) + .hasMessageContaining("overflow"); + } +}]]> + + + + + + + + + + Characteristics of Good Tests (A-TRIP) + Ensuring tests follow A-TRIP principles + + + + + + + processor.addItem(null)) + .isInstanceOf(IllegalArgumentException.class); + } + + // Professional: Code is clean, uses meaningful names, follows conventions. +}]]> + + + + + + + + + + Verifying CORRECT Boundary Conditions + Comprehensive boundary condition testing using CORRECT + + + + + + + + + + + + + + + + + + + **ANALYZE** Java test code to identify gaps in test strategy coverage — RIGHT-BICEP dimensions, A-TRIP characteristics, and CORRECT boundary conditions + **CATEGORIZE** findings by strategy: RIGHT-BICEP (missing Right/Boundary/Inverse/Cross-check/Error/Performance), A-TRIP (Automatic/Thorough/Repeatable/Independent/Professional violations), CORRECT (Conformance/Ordering/Range/Reference/Existence/Cardinality/Time gaps) + **APPLY** testing strategies by adding or refining tests to cover identified gaps using the conceptual frameworks + **IMPLEMENT** comprehensive boundary testing and quality characteristics following RIGHT-BICEP, A-TRIP, and CORRECT principles + **EXPLAIN** the applied strategies and their benefits for test coverage, reliability, and maintainability + **VALIDATE** that all applied changes compile successfully and tests pass + + + + + + **BLOCKING SAFETY CHECK**: ALWAYS run `./mvnw compile` before ANY testing recommendations to ensure project stability + **CRITICAL VALIDATION**: Execute `./mvnw clean verify` to ensure all existing tests pass before implementing new test strategies + **MANDATORY VERIFICATION**: Confirm all existing functionality remains intact after applying any test improvements + **INCREMENTAL SAFETY**: Apply test improvements incrementally, validating compilation and test execution after each modification + + + diff --git a/system-prompts-generator/src/main/resources/system-prompts/131-java-testing-unit-testing.xml b/system-prompts-generator/src/main/resources/system-prompts/131-java-testing-unit-testing.xml index 4f9904c4..7b6fc6f9 100644 --- a/system-prompts-generator/src/main/resources/system-prompts/131-java-testing-unit-testing.xml +++ b/system-prompts-generator/src/main/resources/system-prompts/131-java-testing-unit-testing.xml @@ -666,231 +666,7 @@ class MyProcessorTest { - - - Key Questions to Guide Test Creation (RIGHT-BICEP) - Comprehensive testing approach using RIGHT-BICEP - - - - - - - calculator.add(Integer.MAX_VALUE, 1)) - .isInstanceOf(ArithmeticException.class) - .hasMessageContaining("overflow"); - } -}]]> - - - - - - - - - - Characteristics of Good Tests (A-TRIP) - Ensuring tests follow A-TRIP principles - - - - - - - processor.addItem(null)) - .isInstanceOf(IllegalArgumentException.class); - } - - // Professional: Code is clean, uses meaningful names, follows conventions. -}]]> - - - - - - - - - - Verifying CORRECT Boundary Conditions - Comprehensive boundary condition testing using CORRECT - - - - - - - - - - - - - - - + Avoid Reflection in Unit Tests Test through public API or extract logic to testable components instead of using reflection diff --git a/system-prompts-generator/src/main/resources/system-prompts/assets/java-system-prompts-java-list-template.md b/system-prompts-generator/src/main/resources/system-prompts/assets/java-system-prompts-java-list-template.md index 1a40b127..1ab7c3bc 100644 --- a/system-prompts-generator/src/main/resources/system-prompts/assets/java-system-prompts-java-list-template.md +++ b/system-prompts-generator/src/main/resources/system-prompts/assets/java-system-prompts-java-list-template.md @@ -55,6 +55,7 @@ Use the following collection of System prompts of Java to improve your Java deve | Cursor Rule | Description | Prompt | Notes | |----|----|----|----| +| [130-java-testing-strategies](.cursor/rules/130-java-testing-strategies.md) | Apply testing strategies — RIGHT-BICEP, A-TRIP, CORRECT for boundary conditions and test quality | **User Prompt:** `Improve tests applying testing strategies with @130-java-testing-strategies` **Note:** Add in the context test classes or code under test. Focuses on conceptual frameworks rather than framework-specific annotations. | Use for strategy-focused test design. For JUnit 5, AssertJ, Mockito, use @131-java-testing-unit-testing. | | [131-java-testing-unit-testing](.cursor/rules/131-java-testing-unit-testing.md) | Apply Unit Testing best practices | **User Prompt:** `Improve the class/classes added in the context applying the system prompt @131-java-testing-unit-testing` (Example) **Note:** Add in the context a class/classes. **User Prompt with Consultative Interactive Behaviour:** `Improve the class/classes added in the context applying the system prompt @131-java-testing-unit-testing with the behaviour @behaviour-consultative-interaction` | You can use the System prompt in a purist way or add the Behaviours to customize the final behaviour. | | [132-java-testing-integration-testing](.cursor/rules/132-java-testing-integration-testing.md) | Set up integration test infrastructure with WireMock (REST stubs) and generate a `BaseIntegrationTest.java` with WireMock mapping files | **Interactive User Prompt:** `Set up integration test infrastructure for my service using @132-java-testing-integration-testing` **Note:** The rule will ask questions about your service's outbound HTTP dependencies before generating `BaseIntegrationTest.java` and starter WireMock mapping files. | Interactive rule — asks questions about REST topology before generating code. Framework-agnostic: works with any Java stack. |