Solution tests
3. Premiers tests
Date.java (version incorrecte)
package gloo.date;
public class Date {
private int jour;
private int mois;
private int annee;
public Date( int jour, int mois, int annee ) {
super();
this.jour = jour;
this.mois = mois;
this.annee = annee;
}
public Date lendemain() {
return new Date( jour + 1, mois, annee );
}
}
TestDateLendemainSpec.java
package gloo.date.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import gloo.date.Date;
class TestDateLendemainSpec {
@Test
void testLendemainNotNull() {
Date date = new Date( 18, 1, 2022 );
assertNotNull( date.lendemain() );
}
@Test
void testLendemainNotSame() {
Date date = new Date( 18, 1, 2022 );
assertNotSame( date, date.lendemain() );
}
@Test
void testLendemainSimple() {
Date today = new Date( 18, 1, 2022 );
Date tomorrow = new Date( 19, 1, 2022 );
assertEquals( tomorrow, today.lendemain() );
}
}
Date.java (version corrigée)
package gloo.date;
public class Date {
private int jour;
private int mois;
private int annee;
public Date( int jour, int mois, int annee ) {
super();
this.jour = jour;
this.mois = mois;
this.annee = annee;
}
// hashCode() n'est pas utilisé dans cet exercice, mais si on demande à Eclipse de
// générer equals(), il génère aussi hashcode().
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + annee;
result = prime * result + jour;
result = prime * result + mois;
return result;
}
@Override
public boolean equals( Object obj ) {
if( this == obj ) return true;
if( obj == null ) return false;
if( getClass() != obj.getClass() ) return false;
Date other = ( Date ) obj;
if( annee != other.annee ) return false;
if( jour != other.jour ) return false;
if( mois != other.mois ) return false;
return true;
}
public Date lendemain() {
return new Date( jour + 1, mois, annee );
}
}
4. Prise en compte de la durée des mois
Date.java
package gloo.date;
public class Date {
private static final int NOMBRE_JOURS_MAX = 31;
private static final int NOMBRE_MOIS = 12;
private int jour;
private int mois;
private int annee;
public Date( int jour, int mois, int annee ) {
super();
this.jour = jour;
this.mois = mois;
this.annee = annee;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + annee;
result = prime * result + jour;
result = prime * result + mois;
return result;
}
@Override
public boolean equals( Object obj ) {
if( this == obj ) return true;
if( obj == null ) return false;
if( getClass() != obj.getClass() ) return false;
Date other = ( Date ) obj;
if( annee != other.annee ) return false;
if( jour != other.jour ) return false;
if( mois != other.mois ) return false;
return true;
}
public Date lendemain() {
int j = jour + 1;
int m = mois;
int a = annee;
if( j > nombreJoursDansMois( mois, annee )) {
j = 1;
m += 1;
if( m > NOMBRE_MOIS ) {
m = 1;
a += 1;
}
}
return new Date( j, m, a );
}
private static int nombreJoursDansMois( int mois ) {
return switch( mois ) {
case 1, 3, 5, 7, 8, 10, 12 -> NOMBRE_JOURS_MAX;
case 2 -> NOMBRE_JOURS_MAX - 3;
case 4, 6, 9, 11 -> NOMBRE_JOURS_MAX - 1;
default -> throw new IllegalArgumentException( "Unexpected value: " + mois );
};
}
}
TestDateLendemainFinMois.java
package gloo.date.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import gloo.date.Date;
class TestDateLendemainFinMois {
@Test
void testDateFinJanvier() {
Date actual = new Date( 31, 1, 2022 );
Date expected = new Date( 1, 2, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinFevrier() {
Date actual = new Date( 28, 2, 2022 );
Date expected = new Date( 1, 3, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinMars() {
Date actual = new Date( 31, 3, 2022 );
Date expected = new Date( 1, 4, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinAvril() {
Date actual = new Date( 30, 4, 2022 );
Date expected = new Date( 1, 5, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinMai() {
Date actual = new Date( 31, 5, 2022 );
Date expected = new Date( 1, 6, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinJuin() {
Date actual = new Date( 30, 6, 2022 );
Date expected = new Date( 1, 7, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinJuillet() {
Date actual = new Date( 31, 7, 2022 );
Date expected = new Date( 1, 8, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinAout() {
Date actual = new Date( 31, 8, 2022 );
Date expected = new Date( 1, 9, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinSeptembre() {
Date actual = new Date( 30, 9, 2022 );
Date expected = new Date( 1, 10, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinOctobre() {
Date actual = new Date( 31, 10, 2022 );
Date expected = new Date( 1, 11, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinNovembre() {
Date actual = new Date( 30, 11, 2022 );
Date expected = new Date( 1, 12, 2022 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testDateFinDecembre() {
Date actual = new Date( 31, 12, 2022 );
Date expected = new Date( 1, 1, 2023 );
assertEquals( expected, actual.lendemain() );
}
}
5. Prise en compte des années bisextiles
Date.java
package gloo.date;
public class Date {
private static final int NOMBRE_JOURS_MAX = 31;
private static final int NOMBRE_MOIS = 12;
private int jour;
private int mois;
private int annee;
public Date( int jour, int mois, int annee ) {
super();
this.jour = jour;
this.mois = mois;
this.annee = annee;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + annee;
result = prime * result + jour;
result = prime * result + mois;
return result;
}
@Override
public boolean equals( Object obj ) {
if( this == obj ) return true;
if( obj == null ) return false;
if( getClass() != obj.getClass() ) return false;
Date other = ( Date ) obj;
if( annee != other.annee ) return false;
if( jour != other.jour ) return false;
if( mois != other.mois ) return false;
return true;
}
public Date lendemain() {
int j = jour + 1;
int m = mois;
int a = annee;
if( j > nombreJoursDansMois( mois, annee )) {
j = 1;
m += 1;
if( m > NOMBRE_MOIS ) {
m = 1;
a += 1;
}
}
return new Date( j, m, a );
}
private static int nombreJoursDansMois( int mois, int annee ) {
return switch( mois ) {
case 1, 3, 5, 7, 8, 10, 12 -> NOMBRE_JOURS_MAX;
case 2 -> NOMBRE_JOURS_MAX - ( estBissextile( annee ) ? 2 : 3 );
case 4, 6, 9, 11 -> NOMBRE_JOURS_MAX - 1;
default -> throw new IllegalArgumentException( "Unexpected value: " + mois );
};
}
private static boolean estBissextile( int annee ) {
return annee % 400 == 0 || (( annee % 4 == 0 ) && ( annee % 100 != 0 ));
}
}
TestAnneeBissextile.java
package gloo.date.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import gloo.date.Date;
class TestAnneeBissextile {
@Test
void testAnneeBissectile2008() {
Date actual = new Date( 28, 2, 2008 );
Date expected = new Date( 29, 2, 2008 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testAnneeNonBissectile1900() {
Date actual = new Date( 28, 2, 1900 );
Date expected = new Date( 1, 3, 1900 );
assertEquals( expected, actual.lendemain() );
}
@Test
void testAnneeBissectile2000() {
Date actual = new Date( 28, 2, 2000 );
Date expected = new Date( 29, 2, 2000 );
assertEquals( expected, actual.lendemain() );
}
}
6. Validation des dates initiales
Date.java
package gloo.date;
public class Date {
private static final int NOMBRE_JOURS_MAX = 31;
private static final int NOMBRE_MOIS = 12;
private int jour;
private int mois;
private int annee;
public Date( int jour, int mois, int annee ) {
super();
verifieArguments( jour, mois, annee );
this.jour = jour;
this.mois = mois;
this.annee = annee;
}
private static void verifieArguments( int jour, int mois, int annee ) {
if( jour <= 0 )
throw new IllegalArgumentException( "jour doit être >= 1" );
// Il faut vérifier la validité de mois et annee avant d'utiliser nombreJoursDansMois
if( mois <= 0 )
throw new IllegalArgumentException( "mois doit être >= 1" );
if( mois > NOMBRE_MOIS )
throw new IllegalArgumentException( "mois doit être <= 12" );
if( annee <= 0 )
throw new IllegalArgumentException( "annee doit être >= 1" );
if( jour > nombreJoursDansMois( mois, annee ))
throw new IllegalArgumentException( "jour doit être >= 1" );
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + annee;
result = prime * result + jour;
result = prime * result + mois;
return result;
}
@Override
public boolean equals( Object obj ) {
if( this == obj ) return true;
if( obj == null ) return false;
if( getClass() != obj.getClass() ) return false;
Date other = ( Date ) obj;
if( annee != other.annee ) return false;
if( jour != other.jour ) return false;
if( mois != other.mois ) return false;
return true;
}
public Date lendemain() {
int j = jour + 1;
int m = mois;
int a = annee;
if( j > nombreJoursDansMois( mois, annee )) {
j = 1;
m += 1;
if( m > NOMBRE_MOIS ) {
m = 1;
a += 1;
}
}
return new Date( j, m, a );
}
private static int nombreJoursDansMois( int mois, int annee ) {
return switch( mois ) {
case 1, 3, 5, 7, 8, 10, 12 -> NOMBRE_JOURS_MAX;
case 2 -> NOMBRE_JOURS_MAX - ( estBissextile( annee ) ? 2 : 3 );
case 4, 6, 9, 11 -> NOMBRE_JOURS_MAX - 1;
default -> throw new IllegalArgumentException( "Unexpected value: " + mois );
};
}
private static boolean estBissextile( int annee ) {
return annee % 400 == 0 || (( annee % 4 == 0 ) && ( annee % 100 != 0 ));
}
}
TestConstructeurDate.java
package gloo.date.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import gloo.date.Date;
class TestConstructeurDate {
@Test
void testConstructeurDateValide() {
assertDoesNotThrow( () -> { new Date( 18, 1, 2022 ); } );
}
@Test
void testConstructeurDateInvalideJourNegatif() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( -10, 2, 2020 ); }
);
}
@Test
void testConstructeurDateInvalideJourNul() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 0, 12, 2026 ); }
);
}
@Test
void testConstructeurDateFinJanvier() {
assertDoesNotThrow(
() -> { new Date( 31 , 1, 4126 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 1, 4126 ); }
);
}
@Test
void testConstructeurDateFinFevrier() {
assertDoesNotThrow(
() -> { new Date( 28 , 2, 1111 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 28 + 1, 2, 1111 ); }
);
}
@Test
void testConstructeurDateFinFevrierBissextile() {
assertDoesNotThrow(
() -> { new Date( 29 , 2, 2008 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 29 + 1, 2, 2008 ); }
);
}
@Test
void testConstructeurDateFinMars() {
assertDoesNotThrow(
() -> { new Date( 31 , 3, 3 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 3, 3 ); }
);
}
@Test
void testConstructeurDateFinAvril() {
assertDoesNotThrow(
() -> { new Date( 30 , 4, 9999 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 30 + 1, 4, 9999 ); }
);
}
@Test
void testConstructeurDateFinMai() {
assertDoesNotThrow(
() -> { new Date( 31 , 5, 5555 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 5, 5555 ); }
);
}
@Test
void testConstructeurDateFinJuin() {
assertDoesNotThrow(
() -> { new Date( 30 , 6, 6 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 30 + 1, 6, 6 ); }
);
}
@Test
void testConstructeurDateFinJuillet() {
assertDoesNotThrow(
() -> { new Date( 31 , 7, 123 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 7, 123 ); }
);
}
@Test
void testConstructeurDateFinAout() {
assertDoesNotThrow(
() -> { new Date( 31 , 8, 1 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 8, 1 ); }
);
}
@Test
void testConstructeurDateFinSeptembre() {
assertDoesNotThrow(
() -> { new Date( 30 , 9, 2020 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 30 + 1, 9, 2020 ); }
);
}
@Test
void testConstructeurDateFinOctobre() {
assertDoesNotThrow(
() -> { new Date( 31 , 10, 4040 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 10, 4040 ); }
);
}
@Test
void testConstructeurDateFinNovembre() {
assertDoesNotThrow(
() -> { new Date( 30 , 11, 6060 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 30 + 1, 11, 6060 ); }
);
}
@Test
void testConstructeurDateFinDecembre() {
assertDoesNotThrow(
() -> { new Date( 31 , 12, 12 ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31 + 1, 12, 12 ); }
);
}
@Test
void testDateInvalideMoisNegatif() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 10, -12, 1515 ); }
);
}
@Test
void testDateInvalideMoisNul() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31, 0, 999 ); }
);
}
@Test
void testDateInvalideMoisTropGrand() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 1, 13, 1 ); }
);
}
@Test
void testDateInvalideAnneeNegative() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 20, 2, -1 ); }
);
}
}
7. Meilleure écriture des tests
TestConstructeurDate.java
package gloo.date.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import gloo.date.Date;
class TestConstructeurDate {
@Test
void testConstructeurDateValide() {
assertDoesNotThrow( () -> { new Date( 18, 1, 2022 ); } );
}
@Test
void testConstructeurDateInvalideJourNegatif() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( -10, 2, 2020 ); }
);
}
@Test
void testConstructeurDateInvalideJourNul() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 0, 12, 2026 ); }
);
}
@ParameterizedTest
@CsvSource({ "31, 1, 4126",
"28, 2, 1111",
"29, 2, 2008",
"31, 3, 3",
"30, 4, 9999",
"31, 5, 5555",
"30, 6, 6",
"31, 7, 123",
"31, 8, 1",
"30, 9, 2020",
"31, 10, 4040",
"30, 11, 6060",
"31, 12, 12"
})
void testConstructeurDateFinMois( int j, int m, int a ) {
assertDoesNotThrow(
() -> { new Date( j, m, a ); }
);
assertThrows(
IllegalArgumentException.class,
() -> { new Date( j + 1, m, a ); }
);
}
@Test
void testDateInvalideMoisNegatif() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 10, -12, 1515 ); }
);
}
@Test
void testDateInvalideMoisNul() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 31, 0, 999 ); }
);
}
@Test
void testDateInvalideMoisTropGrand() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 1, 13, 1 ); }
);
}
@Test
void testDateInvalideAnneeNegative() {
assertThrows(
IllegalArgumentException.class,
() -> { new Date( 20, 2, -1 ); }
);
}
}

© 2020-22 CentraleSupélec