Domanda

I am implementing a validator for some userdata.

Unfortunately the userdata contains of a total of 37 fields which makes the test class quite monstrous.

Most of the fields contain data with similar requirements (i.e. checking for length constraints).

Excerpt of the code:

public class Userdata {

    private String            firstName;
    private String            lastName;
    private String            birthName;
    private String            birthPlace;
    private String            city;
    private String            street;
    private String            zipCode;
    private String            country;
    private String            citizenship;

    // getters/setters
}

and (parts of) the test class:

public class UserdataValidatorTest {
    UserdataValidator cut = new UserdataValidator();

    @Test
    public void firstNameMaxPermittedLength()
    {
        Userdata userdata = minimumRequirements();
        userdata.setFirstName( utf8Chars( 64 ) );

        assertNoViolations( cut.validate( userdata ) );
    }

    @Test
    public void firstNameExceedsPermittedLength()
    {
        Userdata userdata = minimumRequirements();
        userdata.setFirstName( utf8Chars( 65 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void lastNameMaxPermittedLength()
    {
        Userdata userdata = minimumRequirements();
        userdata.setLastName( utf8Chars( 64 ) );

        assertNoViolations( cut.validate( userdata ) );
    }

    @Test
    public void lastNameExceedsPermittedLength()
    {
        Userdata userdata = minimumRequirements();
        userdata.setLastName( utf8Chars( 65 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void citizenshipIllegalChars()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCitizenship( "2E" );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void citizenshipLegal()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCitizenship( iso3166Country() );

        assertNoViolations( cut.validate( userdata ) );
    }

    @Test
    public void citizenshipTooLong()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCitizenship( alphabetic( 3 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void citizenshipTooShort()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCitizenship( alphabetic( 1 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void countryIllegalChars()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCountry( "2E" );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void countryLegal()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCountry( iso3166Country() );

        assertNoViolations( cut.validate( userdata ) );
    }

    @Test
    public void countryTooLong()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCountry( alphabetic( 3 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    @Test
    public void countryTooShort()
    {
        Userdata userdata = minimumRequirements();
        userdata.setCountry( alphabetic( 1 ) );

        assertSingleViolation( cut.validate( userdata ) );
    }

    // ... more tests
}

Is there a pleasant way to generate the test cases? I still want to have i.e. 4 tests for each country.

Edit

There are a number of complex (dependent on each other) fields, which I have omitted here, which is a reason why I have decided to not use the Bean Validation API.

È stato utile?

Soluzione

IMHO Unit tests are not production code and don't have to be held up the same standard. You can easy refactor and delete test code without direct impact on production. For me, DRY make sense for production code, but WET (Write Everything Twice) also works in unit test code.

To directly answer your question, you could use a loop, and you could combine the tests, but I suspect they don't help much.

e.g.

@Test
public void firstNameMaxPermittedLength() {
    Userdata userdata = minimumRequirements();
    userdata.setFirstName(utf8Chars(64));
    assertNoViolations(cut.validate(userdata));

    userdata.setFirstName(utf8Chars(65));
    assertSingleViolation(cut.validate(userdata));
}

Altri suggerimenti

If all these fields do the same thing and the names are consistent, why not just ask the class for a list of its methods, loop through all the ones that start with set, and do whatever it is you need to do?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top