Préfixé par 📘, des "checkpoints" pour vous aider à vérifier que vous avez tout bon.
-
Installer Git (cf https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
-
(Sur Windows, avoir un terminal POSIX type Git Bash, la suite de l’exercice est à faire dans celui-ci)
-
Configurer Git avec votre nom et email
-
git config --global user.name "John Doe"
-
git config --global user.email johndoe@example.fr
-
-
Générer une clé SSH (si absente) et donner la partie publique à GitHub (cf https://help.github.com/articles/connecting-to-github-with-ssh/)
-
Installer Java 17 (cf https://adoptium.net/)
-
📘 les commandes
javac -version
etjava -version
doivent afficher la version 17 -
Installer Maven (cf https://maven.apache.org/install.html)
-
📘 la commande
mvn -version
doit afficher la version 3.8.6 -
Installer IntelliJ Community (cf https://www.jetbrains.com/fr-fr/idea/download)
-
Créer un nouveau dépôt Git privé sur la plateforme GitHub avec le nom maven_training initialisé avec un fichier README.md (case à cocher dans le formulaire de création de dépôt)
-
Inviter le professeur actuel comme membre du dépôt (pour la correction)
-
Cloner ce nouveau dépôt en utilisant l'url SSH
-
La branche par défaut est la branche main c’est sur celle-ci que nous allons travailler
-
Ajouter un fichier .editorconfig à la racine du dépôt avec le contenu suivant
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
A quoi ça sert ?
💡
|
Ce fichier (.editorconfig) est reconnu par un grand nombre d’IDE (IntelliJ, Eclipse, VS code, etc.) et va permettre de ne pas avoir à se soucier
Pour plus d’information : https://editorconfig.org/ |
-
ajouter un fichier .gitignore à la racine du dépôt avec le contenu suivant
# IntelliJ
.idea/
*.iml
A quoi ça sert ?
💡
|
Ce fichier (.gitignore) est reconnu par Git afin d’ignorer les changements des fichiers correspondants.
|
-
faire un commit contenant ces deux fichiers avec le message Setup project layout
-
pusher ce nouveau commit (sur votre remote par défaut, en l’occurrence GitHub)
Maven est outil qui gère le cycle de vie d’un projet Java (ou d’autres languages sur la JVM par extension).
Le point d’entrée dans un projet pour Maven est le fichier descripteur du projet appelé pom.xml.
Pour un projet Java, Maven s’attend à trouver le code de production dans le répertoire src/main/java et le code de test dans src/test/java.
Tous les fichiers générés par Maven seront placé dans le répertoire target.
-
créer un fichier pom.xml à la racine du dépôt avec le contenu suivant
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.lernejo</groupId>
<artifactId>maven_training</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
-
créer un fichier Sample.java dans le répertoire src/main/java/fr/lernejo avec le contenu suivant
package fr.lernejo;
import java.util.function.BiFunction;
public class Sample {
public int op(Operation op, int a, int b) {
return op.func.apply(a, b);
}
public int fact(int n) {
if (n < 0) {
throw new IllegalArgumentException("N should be positive");
}
return n == 0 ? 1 : n * fact(n - 1);
}
enum Operation {
ADD((a, b) -> a + b),
MULT((a, b) -> a * b),
;
final BiFunction<Integer, Integer, Integer> func;
Operation(BiFunction<Integer, Integer, Integer> func) {
this.func = func;
}
}
}
-
lancer la commande
mvn compile
-
📘 la classe compilée Sample.class correspondante a été générée dans target/classes/fr/lernejo
-
dans le fichier .gitignore ajouter le contenu suivant afin d’ignorer les fichiers générés par Maven
# Maven
target/
-
📘 avec la commande
git status
trois fichiers apparaissent :-
.gitignore
-
pom.xml
-
src/main/java/fr/lernejo/Sample.java
-
-
faire un commit contenant ces trois modifications avec le message "Setup Maven"
Afin de pouvoir construire le projet sans avoir besoin d’installer Maven, nous allons utiliser Maven Wrapper.
Cet outil permet d’ajouter des scripts (unix et windows) autosuffisant pour le lancement de Maven (comprendre, qui
télécharge les binaires si nécessaires).
-
Executer la commande
mvn -N io.takari:maven:0.7.7:wrapper
-
Ajouter à l’index Git les fichiers résultants en s’assurant que le script mvnw l’est bien en écriture
-
avec la commande
git update-index --add --chmod=+x mvnw
-
ne pas oublier d’indexer les fichiers générés dans le répertoire .mvn visibles avec la commande
ls -al
-
-
Commiter les fichiers résultants avec le message "Setup Maven Wrapper"
L’intégration continue (CI pour Continuous Integration) est un service attaché au projet permet de lancer les
différentes étapes de sa construction à chaque fois qu’un changement est apporté.
Dans cet exercice, nous allons utiliser le service proposé par GitHub.
-
créer un fichier .github/workflows/build.yml avec le contenu
name: Build
on: push
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: '17'
- uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- run: |
java -version
echo $JAVA_HOME
- run: ./mvnw install
- uses: codecov/codecov-action@v1
A quoi ça sert ?
💡
|
Ce fichier (build.yml) est reconnu par GitHub et permet de déclencher à chaque push une construction du projet
|
-
Commiter ce fichier avec le message "Setup GitHub CI"
-
📘 Dans l’interface web GitHub de votre projet, dans l’onglet Actions, un nouveau workflow démarre et celui-ci doit se finir en succès
-
Dans le fichier pom.xml ajouter
-
les quatre properties suivantes
<properties> <!-- balise existante --> ... <junit.version>5.9.1</junit.version> <assertj.version>3.23.1</assertj.version> <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.8</jacoco-maven-plugin.version> </properties>
-
les dépendances suivantes
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
-
et les plugins suivants
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
A quoi ça sert ?
💡
|
Nous ajoutons au projet les dépendances
Par ailleurs, par défaut Maven utilise une version du plugin surefire qui ne reconnaît pas junit-jupiter, c’est pour ça que nous devons le forcer à une version plus récente. |
-
Ouvrir IntelliJ et importer le projet en choisissant
File
→New
→Project from Existing Sources…
et en sélectionnant le fichier pom.xml -
Créer le répertoire src/test/java (clic droit sur
maven_training
→New
→Directory
) qui va accueillir les classes de test -
Ouvrir la classe Java Sample et créer la classe de test correspondante en utilisant le raccourci (Ctrl + Shift + T)
ou par le menuNavigate
→Test
-
Ajouter les tests nécessaires à une couverture du code à 100 %
Qu’est-ce qu’un test ?
💡
|
Un test est constitué de trois parties
Exemples : @Test
void dividing_by_zero_should_produce_an_exception() {
int dividend = 10;
int divisor = 0;
Assertions.assertThatExceptionOfType(DivisionByZeroException.class)
.isThrownBy(() -> Sample.divide(dividend, divisor));
}
@Test
void dividing_10_by_2_should_produce_5() {
int dividend = 10; // (1)
int divisor = 2;
int quotient = Sample.divide(dividend, divisor); // (2)
Assertions.assertThat(quotient).as("quotient of 10 / 2")
.isEqualTo(5); // (3)
}
|
-
Commiter ces changements avec le message "Add test to match 100% coverage"
Pour suivre l’état d’un projet, il peut être plus simple d’afficher des indicateurs visuels sur la page principale.
C’est là l’intérêt des badges. Ces petites images reflètent l’état actuel du projet par rapport aux dernières executions de la CI.
-
Dans le fichier README.md ajouter les badges suivants
-
build CI (cf https://docs.github.com/en/actions/managing-workflow-runs/adding-a-workflow-status-badge)
-
couverture par les tests (cf https://codecov.io/gh/<your-name>/<your-project>/settings/badge)
-
-
Commiter ce changement avec le message "Add live badges"
-
📘 Dans l’interface web GitHub de votre projet, le fichier README affiché par défaut doit contenir les deux badges indiquant que le build est en succès et que la couverture par les tests est de 100 %
💡
|
Si le badge de couverture apparait en gris, il est possible que Codecov n’est pas reçu l’information de couverture. Pour troubleshooter ce problème, vérifier dans les executions de votre workflow de CI (onglet |