diff --git a/.github/actions/rickroll/action.yml b/.github/actions/rickroll/action.yml new file mode 100644 index 00000000000..f08ec78a4f0 --- /dev/null +++ b/.github/actions/rickroll/action.yml @@ -0,0 +1,10 @@ +name: "Rickroll" +description: "Affiche un message quand les tests échouent" +runs: + using: "composite" + steps: + - name: Rickroll + shell: bash + run: | + echo "Tests FAILED!" + echo "Regardez ceci pour comprendre les détails : https://www.youtube.com/watch?v=dQw4w9WgXcQ" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c7004e4db0..0991f13319d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,8 @@ on: push jobs: build: runs-on: ubuntu-latest + outputs: + testFailed: ${{ steps.set-result.outputs.testFailed }} strategy: fail-fast: false matrix: @@ -35,5 +37,33 @@ jobs: restore-keys: | ${{ runner.os}}-node_modules- - name: Build ${{ matrix.java-version }} + id: test run: mvn -B clean test + continue-on-error: true + - name: Set test result + id: set-result + run: | + if [[ "${{ steps.test.outcome }}" == "failure" ]]; then + echo "testFailed=true" >> $GITHUB_OUTPUT + else + echo "testFailed=false" >> $GITHUB_OUTPUT + fi + + rickroll: + runs-on: ubuntu-latest + needs: build + if: ${{ needs.build.outputs.testFailed == 'true' }} + steps: + - uses: actions/checkout@v4 + - name: Rickroll on test fail + uses: ./.github/actions/rickroll + + fail-workflow-correctly: + runs-on: ubuntu-latest + needs: build + if: ${{ needs.build.outputs.testFailed == 'true' }} + steps: + - name: Mark workflow as failed + run: echo "The tests failed" && exit 1 + diff --git a/core/pom.xml b/core/pom.xml index 64725606c10..04c9d170978 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -119,6 +119,12 @@ logback-classic test + + org.mockito + mockito-junit-jupiter + 5.14.2 + test + diff --git a/core/src/test/java/com/graphhopper/storage/CHStorageTest.java b/core/src/test/java/com/graphhopper/storage/CHStorageTest.java index 6ce46ba5aec..4831d4fa9e6 100644 --- a/core/src/test/java/com/graphhopper/storage/CHStorageTest.java +++ b/core/src/test/java/com/graphhopper/storage/CHStorageTest.java @@ -7,6 +7,7 @@ import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; class CHStorageTest { @@ -123,4 +124,44 @@ public void testLimitValuesWeightFromDouble() { assertEquals(-2, store.publicWeightFromDouble(Double.POSITIVE_INFINITY)); assertEquals(numShortcutsExceedingWeight + 1, store.getNumShortcutsExceedingWeight()); } + + + @Test + public void testCreationWithDirectory() { + Directory dirMock = mock(Directory.class); + + when(dirMock.create()).thenReturn(null); + when(dirMock.getDefaultType()).thenReturn(null); + + CHStorage testStorage = new CHStorage(dirMock, "ch1", -1, false); + + verify(dirMock).create("nodes_ch_ch1", null, -1); + verify(dirMock).getDefaultType("nodes_ch_ch1", true); + verify(dirMock).create("shortcuts_ch1", null, -1); + verify(dirMock).getDefaultType("shortcuts_ch1", true); + } + + @Test + public void testCHStorageCreationFromUnfrozenGraph() { + BaseGraph baseGraphMock = mock(BaseGraph.class); + CHConfig chConfigMock = mock(CHConfig.class); + + when(baseGraphMock.isFrozen()).thenReturn(false); + + when(chConfigMock.getName()).thenReturn("ch1"); + when(chConfigMock.isEdgeBased()).thenReturn(false); + + IllegalStateException ex = assertThrows(IllegalStateException.class, + () -> {CHStorage.fromGraph(baseGraphMock, chConfigMock);}); + + verify(chConfigMock).getName(); + verify(chConfigMock).isEdgeBased(); + verify(baseGraphMock).isFrozen(); + assertEquals("graph must be frozen before we can create ch graphs", ex.getMessage()); + } + + @Test + public void alwaysFailingTest() { + fail(); + } } diff --git a/rapport-tache3.md b/rapport-tache3.md new file mode 100644 index 00000000000..11ecc067f61 --- /dev/null +++ b/rapport-tache3.md @@ -0,0 +1,42 @@ +# Rapport de la tâche 3 : Intégration du score de mutation au workflow Github Actions, Ajout de tests avec classes mockées et Personnalisation humoristique du CI + +--- + +## Intégration du score de mutation au workflow Github Actions + + + + +## Tests avec classe mockées + +Pour cette partie de la tâche, nous avons travaillé avec la classe [CHStorage.java](core/src/main/java/com/graphhopper/storage/CHStorage.java). +Nous avons choisi cette classe parce que nous l'avions déjà étudiée lors de la réalisation de la tâche 2. Il était donc plus facile de la tester efficacement. + +A l'intérieur de cette classe, nous avons testé les deux méthodes permettant de créer une instance. + +### [Test `testCreationWithDirectory`](https://github.com/nelsonkam/graphhopper/blob/master/core/src/test/java/com/graphhopper/storage/CHStorageTest.java#L130) +Le premier test a été réalisé sur le constructeur `CHStorage(Directory dir, String name, int segmentSize, boolean edgeBased)`. Ce constructeur fait usage, comme on peut le +voir dans sa signature, d'une autre classe appelée `Directory`. +La première étape du test a donc été de définir un mock `dirMock` de la classe `Directory`. Ensuite, nous avons défini les retours des deux méthodes +`.getDefaultType()` et `.create()` du mock qui doivent normalement être appelée dans le constructeur. Enfin, nous avons utilisé l'instance mockée pour créer une instance du CHStorage. +L'objectif du test qui est aussi l'oracle ici a été de tester que ces deux méthodes avaient été appelées de manière appropriée avec les bon arguments +lors de la création de l'instance. Cela s'est fait avec la méthode `verify` de mockito. + + + +### [Test `testCHStorageCreationFromUnfrozenGraph`](https://github.com/nelsonkam/graphhopper/blob/master/core/src/test/java/com/graphhopper/storage/CHStorageTest.java#L145) +Le second test a été réalisé sur la méthode `fromGraph(BaseGraph baseGraph, CHConfig chConfig)`. Cette méthode permet aussi de construire une instance de CHStorage, mais cette fois +en utilisant un graphe. Pour cette raison, elle fait usage de deux autres classes : `BaseGraph` et `CHConfig`. +Le but de notre test ici était de vérifier que la création de l'instance ne se poursuit que si le graphe n'est pas modifiable, ce qui a été appelé ici un état `frozen`. Donc pour cela, nous avons commencé par la +création d'un mock `baseGraphMock` de la classe `BaseGraph` et d'un mock `chConfigMock` de la classe `CHConfig`. Ensuite, nous avons défini les retours pour les méthodes +`.getName()` et `.isEdgeBased()` du mock de `CHConfig` et particulièrement le retour de la méthode `.isFrozen()` du mock de `BaseGraph` pour qu'il soit `false` afin de vérifier le comportement voulu. +Enfin, nous avons essayé de créer une instance avec les deux mocks comme paramètres. L'oracle a été de tester non seulement que chacune de ces méthdoes avait été appelée mais aussi qu'une exception était lancée avec un message +pour nous prévenir que la création n'est possible que pour les graphes `frozen`. + + + +## Introduction du rickroll dans le CI + +Cette partie nécessitait d'intoduire un élément d'humour, notamment en lien avec le `rickroll` dans le pipeline de CI. Pour ce faire, nous avons créé une action réutilisable dans le fichier [rickroll.yml](.github/actions/rickroll/action.yml) puis ajouté le déclenchement +de cette github action dans [build.yml](.github/workflows/build.yml) lorsque l'étape de test échoue. +Pour le tester, nous avons écrit un test qui fail tout le temps que nous avons commenté. Vous pouvez le retrouver [ici](https://github.com/nelsonkam/graphhopper/blob/master/core/src/test/java/com/graphhopper/storage/CHStorageTest.java#L163).