From ff27e67e1f66e500de62afe4adf6c4d70d39e870 Mon Sep 17 00:00:00 2001 From: Andrei Solntsev Date: Fri, 6 Dec 2024 11:20:58 +0200 Subject: [PATCH] simplify few tests I see that @ParametrizedTest may be over-used. It causes "IFs" and logic in tests trying to handle all given values. Sometimes it's better to just write plain old test without any IFs. --- .../datafaker/idnumbers/SwedenIdNumber.java | 11 +- .../datafaker/helpers/IdNumberPatterns.java | 1 + .../idnumbers/PolishIdNumberTest.java | 197 +++++++----------- .../idnumbers/SwedishIdNumberTest.java | 73 ++++--- 4 files changed, 125 insertions(+), 157 deletions(-) diff --git a/src/main/java/net/datafaker/idnumbers/SwedenIdNumber.java b/src/main/java/net/datafaker/idnumbers/SwedenIdNumber.java index 0b487cc30..72f3f13d6 100644 --- a/src/main/java/net/datafaker/idnumbers/SwedenIdNumber.java +++ b/src/main/java/net/datafaker/idnumbers/SwedenIdNumber.java @@ -49,10 +49,13 @@ private String generateSymbol(LocalDate date){ return isYearOver100YearsAgo(date.toString().substring(0, 4), LocalDate.now()) ? "+" : "-"; } - public static String generateEndPart(BaseProviders f) { + private String generateEndPart(BaseProviders f) { return "%03d".formatted(f.number().numberBetween(1, 1000)); } + /** + * @deprecated Use method {@link #generateInvalid(BaseProviders)} instead + */ @Deprecated public String getInvalidSsn(BaseProviders f) { return generateInvalid(f); @@ -62,17 +65,13 @@ public String getInvalidSsn(BaseProviders f) { public String generateInvalid(BaseProviders f) { String candidate = "121212-1212"; // Seed with a valid number while (isValidSwedishSsn(candidate)) { - String pattern = getPattern(f); + String pattern = f.options().option(VALID_PATTERNS); candidate = f.numerify(pattern); } return candidate; } - private String getPattern(BaseProviders faker) { - return faker.options().option(VALID_PATTERNS); - } - public static boolean isValidSwedishSsn(String ssn) { if (ssn.length() != 11) { return false; diff --git a/src/test/java/net/datafaker/helpers/IdNumberPatterns.java b/src/test/java/net/datafaker/helpers/IdNumberPatterns.java index 874d21d7c..cc069dbee 100644 --- a/src/test/java/net/datafaker/helpers/IdNumberPatterns.java +++ b/src/test/java/net/datafaker/helpers/IdNumberPatterns.java @@ -9,5 +9,6 @@ public class IdNumberPatterns { public static final Pattern SOUTH_AFRICAN = Pattern.compile("[0-9]{10}([01])8[0-9]"); public static final Pattern FRENCH = Pattern.compile("[12]\\d{2}(1[0-2]|0[1-9])\\d[0-9a-zA-Z]\\d{8}"); public static final Pattern ITALIAN = Pattern.compile("[A-Z]{6}\\d{2}[ABCDEHLMPRST]\\d{2}[\\dA-Z]{5}"); + public static final Pattern POLISH = Pattern.compile("\\d{11}"); } diff --git a/src/test/java/net/datafaker/idnumbers/PolishIdNumberTest.java b/src/test/java/net/datafaker/idnumbers/PolishIdNumberTest.java index 2a94532c8..de3fd8f20 100644 --- a/src/test/java/net/datafaker/idnumbers/PolishIdNumberTest.java +++ b/src/test/java/net/datafaker/idnumbers/PolishIdNumberTest.java @@ -3,148 +3,115 @@ import net.datafaker.Faker; import net.datafaker.idnumbers.PolishIdNumber.Gender; import net.datafaker.providers.base.BaseFaker; +import net.datafaker.providers.base.IdNumber.IdNumberRequest; +import net.datafaker.providers.base.PersonIdNumber; +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; import java.time.LocalDate; import java.util.Locale; +import static java.lang.Integer.parseInt; +import static net.datafaker.helpers.IdNumberPatterns.POLISH; +import static net.datafaker.providers.base.IdNumber.GenderRequest.ANY; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.fail; class PolishIdNumberTest { - public static final int PESEL_EXPECTED_LENGTH = 11; - private static final Faker faker = new Faker(new Locale("pl", "PL")); private static final PolishIdNumber peselNumber = new PolishIdNumber(); - @ParameterizedTest - @EnumSource(value = Gender.class, names = {"MALE", "FEMALE"}) - void testGenderedPesel(Gender givenGender) { - /* - * Given - */ - final LocalDate givenBirthDate = new BaseFaker().timeAndDate().birthday(0, 100); - /* - * When - */ - final String gotPesel = peselNumber.get(faker, givenBirthDate, givenGender); - - /* - * Then - */ - assertBasics(gotPesel); - assertBirthDate(givenBirthDate, gotPesel); - assertGender(givenGender, gotPesel); - assertControlDigit(gotPesel); + @RepeatedTest(100) + void idNumberConsistsOf11Digits() { + PersonIdNumber actual = peselNumber.generateValid(faker, new IdNumberRequest(0, 222, ANY)); + + assertThat(actual.idNumber()).matches(POLISH); + assertThat(year(actual.idNumber()) % 100).isEqualTo(actual.birthDate().getYear() % 100); + assertThat(day(actual.idNumber())).isEqualTo(actual.birthDate().getDayOfMonth()); + assertControlDigit(actual.idNumber()); + } + + @Test + @SuppressWarnings("deprecation") + void generateIdNumberForFemale() { + LocalDate birthDate = new BaseFaker().timeAndDate().birthday(0, 100); + String actual = peselNumber.get(faker, birthDate, Gender.FEMALE); + + assertThat(getGenderDigit(actual) % 2).isZero(); + } + + @Test + @SuppressWarnings("deprecation") + void generateIdNumberForMale() { + LocalDate birthDate = new BaseFaker().timeAndDate().birthday(0, 100); + String actual = peselNumber.get(faker, birthDate, Gender.MALE); + + assertThat(getGenderDigit(actual) % 2).isOne(); + } + + @Test + void centuryIsEncodedInMonthNumber() { + assertThat(month(bornAt(6, 1800))).isEqualTo(86); + assertThat(month(bornAt(6, 1801))).isEqualTo(86); + assertThat(month(bornAt(6, 1899))).isEqualTo(86); + assertThat(month(bornAt(3, 1900))).isEqualTo(3); + assertThat(month(bornAt(3, 1950))).isEqualTo(3); + assertThat(month(bornAt(3, 1999))).isEqualTo(3); + assertThat(month(bornAt(5, 2000))).isEqualTo(25); + assertThat(month(bornAt(5, 2001))).isEqualTo(25); + assertThat(month(bornAt(5, 2050))).isEqualTo(25); + assertThat(month(bornAt(5, 2099))).isEqualTo(25); + assertThat(month(bornAt(5, 2100))).isEqualTo(45); + assertThat(month(bornAt(5, 2199))).isEqualTo(45); + assertThat(month(bornAt(5, 2200))).isEqualTo(65); + assertThat(month(bornAt(5, 2299))).isEqualTo(65); } @ParameterizedTest - @ValueSource(ints = {1850, 1950, 2050, 2150, 2250}) - void testCenturiesPesel(int givenBirthYear) { - /* - * Given - */ - final LocalDate givenBirthDate = LocalDate.of(givenBirthYear, 6, 28); - - /* - * When - */ - final String gotPesel = peselNumber.get(faker, givenBirthDate, Gender.ANY); - - /* - * Then - */ - assertBasics(gotPesel); - assertBirthDate(givenBirthDate, gotPesel); - assertControlDigit(gotPesel); + @ValueSource(ints = {-100, 1699, 1799}) + @SuppressWarnings("deprecation") + void tooEarlyCenturies(int birthYear) { + LocalDate birthDate = LocalDate.of(birthYear, 6, 28); + + assertThatThrownBy(() -> peselNumber.get(faker, birthDate, Gender.ANY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Year is before 1800: %s", birthYear); } @ParameterizedTest - @ValueSource(ints = {1799, 2300}) - void testInvalidCenturiesPesel(int givenBirthYear) { - /* - * Given - */ - final LocalDate givenBirthDate = LocalDate.of(givenBirthYear, 6, 28); - - /* - * When - */ - assertThatThrownBy(() -> peselNumber.get(faker, givenBirthDate, Gender.ANY)) - .isInstanceOf(IllegalArgumentException.class); + @ValueSource(ints = {2300, 2399, 9999}) + @SuppressWarnings("deprecation") + void tooLateCenturies(int birthYear) { + LocalDate birthDate = LocalDate.of(birthYear, 6, 28); + + assertThatThrownBy(() -> peselNumber.get(faker, birthDate, Gender.ANY)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Year is after 2300: %s", birthYear); } - @Test - void testNullGender() { - /* - * Given - */ - final LocalDate givenBirthDate = LocalDate.now(); - - /* - * When - */ - final String gotPesel = peselNumber.get(faker, givenBirthDate, null); - - /* - * Then - */ - assertBasics(gotPesel); - assertBirthDate(givenBirthDate, gotPesel); - assertControlDigit(gotPesel); + private int getGenderDigit(String idNumber) { + return idNumber.charAt(9) - '0'; } - private void assertBasics(String gotPesel) { - assertThat(gotPesel).hasSize(PESEL_EXPECTED_LENGTH); - assertThat(gotPesel.chars().allMatch(Character::isDigit)).isTrue(); + @SuppressWarnings("deprecation") + private String bornAt(int month, int year) { + LocalDate birthDate = LocalDate.of(year, month, 28); + return peselNumber.get(faker, birthDate, Gender.ANY); } - private void assertBirthDate(LocalDate givenBirthDate, String gotPesel) { - final int gotYear = toNumber(gotPesel.charAt(0), gotPesel.charAt(1)); - assertThat(givenBirthDate.getYear() % 100).isEqualTo(gotYear); - - final int gotMonth = toNumber(gotPesel.charAt(2), gotPesel.charAt(3)); - - final int givenYear = givenBirthDate.getYear(); - - if (givenYear < 1800) { - fail("Year is before 1800. Test case is broken."); - } else if (givenYear < 1900) { - assertThat(givenBirthDate.getMonthValue() + 80).isEqualTo(gotMonth); - } else if (givenYear < 2000) { - assertThat(givenBirthDate.getMonthValue()).isEqualTo(gotMonth); - } else if (givenYear < 2100) { - assertThat(givenBirthDate.getMonthValue() + 20).isEqualTo(gotMonth); - } else if (givenYear < 2200) { - assertThat(givenBirthDate.getMonthValue() + 40).isEqualTo(gotMonth); - } else if (givenYear < 2300) { - assertThat(givenBirthDate.getMonthValue() + 60).isEqualTo(gotMonth); - } else { - throw new IllegalArgumentException("Year %s is after 2300. Test case is broken.".formatted(givenYear)); - } - - final int gotDay = toNumber(gotPesel.charAt(4), gotPesel.charAt(5)); - assertThat(givenBirthDate.getDayOfMonth()).isEqualTo(gotDay); + private int year(String idNumber) { + return parseInt(idNumber.substring(0, 2)); } - private void assertGender(Gender givenGender, String gotPesel) { - final int gotGenderDigit = gotPesel.charAt(9) - '0'; - switch (givenGender) { - case FEMALE: - assertThat(gotGenderDigit % 2).isZero(); - break; - case MALE: - assertThat(gotGenderDigit % 2).isOne(); - break; - case ANY: - default: - break; - } + private int month(String idNumber) { + return parseInt(idNumber.substring(2, 4)); + } + + private int day(String idNumber) { + return parseInt(idNumber.substring(4, 6)); } private void assertControlDigit(String gotPesel) { @@ -153,8 +120,4 @@ private void assertControlDigit(String gotPesel) { + 7 * (gotPesel.charAt(2) + gotPesel.charAt(6)) + 9 * (gotPesel.charAt(3) + gotPesel.charAt(7))) % 10; assertThat(gotSum).isZero(); } - - private int toNumber(char digit2, char digit1) { - return (digit2 - '0') * 10 + digit1 - '0'; - } } diff --git a/src/test/java/net/datafaker/idnumbers/SwedishIdNumberTest.java b/src/test/java/net/datafaker/idnumbers/SwedishIdNumberTest.java index fa04cd0ba..5a05f1660 100644 --- a/src/test/java/net/datafaker/idnumbers/SwedishIdNumberTest.java +++ b/src/test/java/net/datafaker/idnumbers/SwedishIdNumberTest.java @@ -1,16 +1,33 @@ package net.datafaker.idnumbers; +import net.datafaker.Faker; +import net.datafaker.providers.base.IdNumber.IdNumberRequest; +import net.datafaker.providers.base.PersonIdNumber; +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; import java.time.LocalDate; -import java.util.stream.Stream; +import static net.datafaker.providers.base.IdNumber.GenderRequest.ANY; import static org.assertj.core.api.Assertions.assertThat; class SwedishIdNumberTest { + private final Faker faker = new Faker(); + private final SwedenIdNumber impl = new SwedenIdNumber(); + + @RepeatedTest(20) + void swedishSsn_containsPlus_forPersonsOlderThan100Years() { + PersonIdNumber person = impl.generateValid(faker, new IdNumberRequest(101, 125, ANY)); + assertThat(person.idNumber()).matches("(\\d{6})\\+(\\d{4})"); + assertThat(SwedenIdNumber.isValidSwedishSsn(person.idNumber())).as(person.idNumber()).isTrue(); + } + + @RepeatedTest(20) + void swedishSsn_containsMinus_forPersonsYoungerThan100Years() { + PersonIdNumber person = impl.generateValid(faker, new IdNumberRequest(23, 99, ANY)); + assertThat(person.idNumber()).matches("(\\d{6})-(\\d{4})"); + assertThat(SwedenIdNumber.isValidSwedishSsn(person.idNumber())).as(person.idNumber()).isTrue(); + } @Test void validSwedishSsn() { @@ -33,37 +50,25 @@ void invalidSwedishSsn() { assertThat(SwedenIdNumber.isValidSwedishSsn("000229+9873")).isFalse(); } - @ParameterizedTest - @MethodSource("getYears") - void testIsYearOver100YearsAgo(String year, boolean value) { - assertThat(SwedenIdNumber.isYearOver100YearsAgo(year, LocalDate.of(2024, 6, 1))).isEqualTo(value); - } - - private static Stream getYears() { - return Stream.of( - Arguments.of("1900", true), - Arguments.of("1918", true), - Arguments.of("1924", true), - Arguments.of("1990", false), - Arguments.of("2003", false), - Arguments.of("2035", false) - ); - } - - @ParameterizedTest - @MethodSource("provideSsnForFindYearBeginning") - void testFindYearBeginningFromSsn(String ssn, String expectedYearBeginning) { - assertThat(SwedenIdNumber.findYearBeginningFromSsn(ssn)).isEqualTo(expectedYearBeginning); + @Test + void isYearOver100YearsAgo() { + LocalDate today = LocalDate.of(2024, 6, 1); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("1900", today)).isTrue(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("1918", today)).isTrue(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("1924", today)).isTrue(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("1925", today)).isFalse(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("1990", today)).isFalse(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("2003", today)).isFalse(); + assertThat(SwedenIdNumber.isYearOver100YearsAgo("2035", today)).isFalse(); } - private static Stream provideSsnForFindYearBeginning() { - return Stream.of( - Arguments.of("670919-9530", "19"), - Arguments.of("811228-9874", "19"), - Arguments.of("000225-9873", "20"), - Arguments.of("000225+9877", "19"), - Arguments.of("991221+4146", "18"), - Arguments.of("981227+0262", "18") - ); + @Test + void findYearBeginningFromSsn() { + assertThat(SwedenIdNumber.findYearBeginningFromSsn("670919-9530")).isEqualTo("19"); + assertThat(SwedenIdNumber.findYearBeginningFromSsn("811228-9874")).isEqualTo("19"); + assertThat(SwedenIdNumber.findYearBeginningFromSsn("000225-9873")).isEqualTo("20"); + assertThat(SwedenIdNumber.findYearBeginningFromSsn("000225+9877")).isEqualTo("19"); + assertThat(SwedenIdNumber.findYearBeginningFromSsn("991221+4146")).isEqualTo("18"); + assertThat(SwedenIdNumber.findYearBeginningFromSsn("981227+0262")).isEqualTo("18"); } }