Assertions in called method detection (S2699)


(Ewa Śliwińska) #1

I need to perform exactly the same test on the system with just one parameter changed.
I put all assertions in unit test class private method, which actually perform the test, and I call it with this parameter.

Unfortunately, it raises S2699 rule. I think it should not be like this, because there are assertions in this test method, just deeper. Is there a possibility for Sonar to check for assertions in called private methods and disable the violation there?

@Test
public void testOutputForVersion1()
{
   this.complicatedTest( 1 );
}

@Test
public void testOutputForVersion2()
{
   this.complicatedTest( 2 );
}

private void complicatedTest( final int parameter )
{
  // assertions
}

(Adam Gabryś) #2

Hello Ewa,
I agree that such feature will be nice. Unfortunately, I think it won’t be available soon (I saw a lot of posts about this problem before). Luckily, there are better approaches to execute parameterized tests. You can use for example JUnitParams library.

Example:

package biz.gabrys.maven.plugins.css.splitter.steadystate;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;

import biz.gabrys.maven.plugins.css.splitter.css.Standard;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

@RunWith(JUnitParamsRunner.class)
public final class ParserOptionsBuilderTest {

    @Test
    @Parameters(method = "allStandards")
    public void create_checkStandards(final Standard standard) {
        final ParserOptions options = new ParserOptionsBuilder().withStandard(standard).create();
        assertThat(options.getStandard()).isSameAs(standard);
    }

    public static Standard[] allStandards() {
        return Standard.values();
    }

    @Test
    @Parameters({ "true", "false" })
    public void create_checkStrict(final boolean strict) {
        final ParserOptions options = new ParserOptionsBuilder().withStrict(strict).create();
        assertThat(options.isStrict()).isEqualTo(strict);
    }

    @Test
    @Parameters({ "true", "false" })
    public void create_checkStarHack(final boolean allowed) {
        final ParserOptions options = new ParserOptionsBuilder().withStarHack(allowed).create();
        assertThat(options.isStarHackAllowed()).isEqualTo(allowed);
    }
}

As you see it allows you to:

  • create parameters by a factory method
  • convert string to parameters

Cheers


(Ewa Śliwińska) #3

I’m not sure if this will justify importing additional library to our project.
Is there a feature requests list anywhere, the one on which I could vote?

I searched before posting this question and I din’t find similar topic.


(Adam Gabryś) #4

As I wrote, using parameterized tests are recommended approach. JUnit 4 provides parametrized tests (not very develper-friendly), but JUnit 5 provides mechanism similar as I presented in the above example.

There is a Jira ticket SONARJAVA-2192 which has been created at 15th March 2017. I checked it a moment ago, and this information will make you happy :wink: It has been fixed 3 days ago. SonarJava 5.11 will (it has not been released yet) solve all your problems :slight_smile: