openrewrite / openrewrite/rewrite-testing-frameworks

Use Parameterized Tests. RSPEC-5976

Open
#203 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

recipe
Dominant language
Java
Stars
100
Forks
105
Avg merge
2h 25m
Merged PRs (30d)
9

Description

Is this something that could be achieved with this framework?

When multiple tests differ only by a few hardcoded values they should be refactored as a single "parameterized" test. This reduces the chances of adding a bug and makes them more readable. Parameterized tests exist in most test frameworks (JUnit, TestNG, etc...).

The right balance needs of course to be found. There is no point in factorizing test methods when the parameterized version is a lot more complex than initial tests.

This rule raises an issue when at least 3 tests could be refactored as one parameterized test with less than 4 parameters. Only test methods which have at least one duplicated statement are considered.

Noncompliant Code Example
with JUnit 5

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class AppTest
{
@Test
void test_not_null1() { // Noncompliant. The 3 following tests differ only by one hardcoded number.
setupTax();
assertNotNull(getTax(1));
}

@Test
void test_not_null2() {
  setupTax();
  assertNotNull(getTax(2));
}

@Test
void test_not_nul3l() {
  setupTax();
  assertNotNull(getTax(3));
}

@Test
void testLevel1() {  // Noncompliant. The 3 following tests differ only by a few hardcoded numbers.
    setLevel(1);
    runGame();
    assertEquals(playerHealth(), 100);
}

@Test
void testLevel2() {  // Similar test
    setLevel(2);
    runGame();
    assertEquals(playerHealth(), 200);
}

@Test
void testLevel3() {  // Similar test
    setLevel(3);
    runGame();
    assertEquals(playerHealth(), 300);
}

}
Compliant Solution
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

public class AppTest
{

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void test_not_null(int arg) {
setupTax();
assertNotNull(getTax(arg));
}

@ParameterizedTest
@CsvSource({
    "1, 100",
    "2, 200",
    "3, 300",
})
void testLevels(int level, int health) {
    setLevel(level);
    runGame();
    assertEquals(playerHealth(), health);
}

}

Read more : https://rules.sonarsource.com/java/RSPEC-5976?search=tests

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No implementation file or test path is named. Start by reviewing the repository's existing Java testing recipes and their tests, then compare the expected behavior with the linked RSPEC-5976 rule. Done means the framework can address the rule's parameterized-test cases and has coverage for the described examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
testing-qa
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.