Slide 1

Slide 1 text

Robin Caroff U Tech - GDG Nantes Android U Tech Etienne Priou Screenshot Testing pour Compose Preview

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

C’est quoi des screenshots test ?

Slide 4

Slide 4 text

🤔

Slide 5

Slide 5 text

Un système de screenshots tests permet d’effectuer automatiquement cette comparaison et de produire un rapport. Avec le rapport, deux réponses possibles : Il y a une erreur dans le nouveau code on la corrige. 🐛 On approuve la nouvelle capture d'écran et on remplace l'image de référence par la nouvelle. ✅

Slide 6

Slide 6 text

Avantages 😀 Plusieurs assertions à la fois 😀 Pas d’écriture de tests nécessaire 😀 Facile à maintenir 😀 Très utile pour la détection de régression sur différentes configurations Inconvénients 😒 Génère beaucoup d’images 😒 Peut être plus compliqué à débugger quand un composant affecte plusieurs screenshots 😒 Variation acceptable difficile à définir

Slide 7

Slide 7 text

Google’s Compose Preview Screenshot Testing

Slide 8

Slide 8 text

Maturité ● Annoncé en 2024 Google IO ● Développement actif (alpha-8) ● Pas de roadmap visible ● Issue Tracker actif ● Pas open source

Slide 9

Slide 9 text

Rapide à mettre en place ● Kotlin Version: Version 1.9.20 minimum. ● Android Gradle Plugin: Version 8.5.0-beta01 minimum. ● Utiliser Jetpack Compose pour les vues ● Nécessité de créer des fichiers de tests spécifiques

Slide 10

Slide 10 text

Comment fonctionne ? ● Utilise les annotation @Preview dans des fichiers de tests afin de générer des screenshots de référence. ./gradlew updateDebugScreenshotTest ● Le plugin va génère de nouveaux screenshots et les compare avec les références afin de valider les tests avec la commande ./gradlew validateDebugScreenshotTest. ● Les résultats sont consultable via un rapport html simple à comprendre

Slide 11

Slide 11 text

Quelles autres solutions existent ?

Slide 12

Slide 12 text

Quelles solutions open source existent ? Outil Rapidité Configuration Support Compose CI/CD Communauté Création Paparazzi ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ 2019 Roborazzi ⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ ⭐⭐⭐⭐ ⭐⭐⭐ 2022 Shot ⭐⭐⭐ ⭐⭐⭐⭐⭐ ✅ ⭐⭐⭐ ⭐⭐⭐ 2017 Facebook ⭐⭐ ⭐⭐ ❌ ⭐⭐⭐ ⭐⭐⭐ 2015 Dropshots ⭐⭐⭐ ⭐⭐⭐ ❌ ⭐⭐⭐ ⭐⭐ 2018

Slide 13

Slide 13 text

Du code 󰳕

Slide 14

Slide 14 text

Comment fonctionne ? @Composable fun CallCard( userName: String, modifier: Modifier = Modifier, ){ Card( modifier = modifier, shape = RoundedCornerShape(8.dp), ) { Column( modifier = Modifier . padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally , ) { Icon( imageVector = Icons.Rounded. Call, contentDescription = "Call Icon" ) Text(userName) } } } @Composable @Preview internal fun CallCardPreview () { CallCard("Robin") }

Slide 15

Slide 15 text

Comment fonctionne ? ./gradlew updateDebugScreenshotTest class CallCardScreenshots { @Preview @Composable fun CallCardPreviewTest () { CallCardPreview () } }

Slide 16

Slide 16 text

Comment fonctionne ? @Composable fun CallCard( userName: String, modifier: Modifier = Modifier, ){ Card( modifier = modifier, shape = RoundedCornerShape(7.dp), ) { Column( modifier = Modifier . padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally , ) { Icon( imageVector = Icons.Rounded. Call, contentDescription = "Call Icon" ) Text(userName) } } } @Composable @Preview fun CallCardPreview () { CallCard("Robin") } ./gradlew validateDebugScreenshotTest

Slide 17

Slide 17 text

Comment fonctionne ?

Slide 18

Slide 18 text

👀 Custom Test Previews

Slide 19

Slide 19 text

Custom Test Previews @Preview @PreviewFrench @PreviewsUOrientation @PreviewsUFontScale @PreviewLightDark annotation class PreviewScreenshotTest @Preview( name = "Landscape Mode" , showBackground = true, device = Devices. AUTOMOTIVE_1024p , widthDp = 640 ) @Preview(name = "Portrait Mode" , showBackground = true) annotation class PreviewsUOrientation @Preview(name = "Default Font Size" , fontScale = 1f) @Preview(name = "Large Font Size" , fontScale = 1.5f) annotation class PreviewsUFontScale @Preview(locale = "fr") annotation class PreviewFrench

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

🚀 Démo !

Slide 22

Slide 22 text

Mise en place d’une CI avec Github Actions

Slide 23

Slide 23 text

CI/CD - exemple avec Github Actions - name: Run screenshot tests run: ./gradlew :app:validateDebugScreenshotTest - name: Upload screenshot test report if: always() uses: actions/upload-artifact@v4 with: name: screenshot-test-report path: app/build/reports/screenshotTest/

Slide 24

Slide 24 text

Slide 25

Slide 25 text

Les couleurs peuvent être différentes d’un OS à l’autre

Slide 26

Slide 26 text

Autoriser un seuil de différence testOptions { screenshotTests { imageDifferenceThreshold = 0.02f // 0.2% } } #app/build.gradle.kts 📎Image Thresholding in Image Processing

Slide 27

Slide 27 text

Les couleurs peuvent être différentes d’un OS à l’autre

Slide 28

Slide 28 text

Et Git dans tout ça ?

Slide 29

Slide 29 text

Git LFS # Installation de Git LFS git lfs install # Configuration pour les screenshots git lfs track "**/*.png" # Ajout du fichier .gitattributes git add .gitattributes

Slide 30

Slide 30 text

Git LFS 👌 Bonnes pratiques : ● Mettre en place Git LFS dès le début du projet ● Documenter la configuration LFS dans le README du projet ● S'assurer que tous les membres de l'équipe ont Git LFS installé ● Définir une stratégie de nettoyage des anciennes images

Slide 31

Slide 31 text

Suppression de l’historique git filter-repo \ --path 'app/src/debug/screenshotTest' \ --invert-paths \ --force \ --before='1 year ago' git lfs prune # Une fois la PR mergée git lfs prune --force git gc --aggressive

Slide 32

Slide 32 text

Avantages 😀 Simple à mettre en place 😀 Automatisation facilitée 😀 Tests JVM ⇒ Execution rapide Inconvénients 😒 Pas open source 😒 En cours de développement 😒 Faible documentation 😒 Le rendu peut varier selon l’OS et générer des faux positifs ⚠ Attention à l’utilisation de Git 🍿 Takeaway - Compose Preview Screenshot testing

Slide 33

Slide 33 text

Robin Caroff U Tech - GDG Nantes Android U Tech Etienne Priou Screenshot Testing pour Compose Preview