Premiers pas avec le test des applications Scala Spark à l’aide de ScalaTest

Essai est un aspect essentiel du développement de logiciels, en particulier pour applications de mégadonnées où la précision et la performance sont cruciales. Lorsque vous travaillez avec Scala et Apache Spark, les tests peuvent s’avérer difficiles en raison de la nature distribuée de Spark et de la complexité des pipelines de données. Heureusement, ScalaTest fournit un cadre robuste pour écrire et gérer efficacement vos tests.
Dans ce blog, nous explorerons les sujets suivants :
- Un aperçu de ScalaTest
- Défis courants lors du test des applications Spark
- Sélection des styles de test appropriés
- Définir des classes de tests de base
- Rédiger des cas de tests efficaces
- Utiliser des assertions
- Exécution de tests
Défis liés aux tests des applications Scala Spark
Avant d’expliquer comment procéder aux tests à l’aide de ScalaTest, parlons des défis liés aux tests des applications Spark.
- Environnement distribué :
- Étant donné que l’application Spark traite les données dans un environnement distribué, tester de telles applications peut être complexe. Vous devrez vous assurer que vos tests gèrent correctement l’exécution distribuée, la gestion de la mémoire et les problèmes de réseau.
- Il est également fastidieux de reproduire le contexte exact d’exécution dans les tests.
- Contexte d’exécution :
- Les actions et transformations Spark peuvent se comporter différemment en fonction de la localité des données et du partitionnement, ce qui rend difficile le test des cas extrêmes.
- Grands ensembles de données :
- Les applications Spark traitent généralement de grands ensembles de données, ce qui rend difficile la simulation de scénarios de type production lors des tests. Vous devez trouver un équilibre entre la taille des données de test et les scénarios réels.
- Évaluation paresseuse :
- Le modèle d’évaluation paresseux de Spark peut conduire à un comportement inattendu dans les tests s’il n’est pas géré efficacement.
- Longues durées d’exécution des tests :
- Si les tests impliquent plusieurs étapes, remaniements ou transformations complexes, leur exécution peut prendre beaucoup de temps, ce qui ralentit le développement.
En savoir plus: Spark avec Pytest : façonner l’avenir des tests de données
ScalaTest
- Dans ScalaTest, le concept central est la suite, qui est une collection d’un ou plusieurs tests.
- Un test est tout ce qui a un nom, qui peut être démarré et qui peut réussir, échouer, être marqué comme en attente ou être annulé.
- ScalaTest fournit des traits de style qui étendent Suite et remplacent les méthodes de cycle de vie, prenant en charge différentes approches de test.
- Trait Suite déclare run et d’autres méthodes de « cycle de vie » qui définissent une manière par défaut d’écrire et d’exécuter des tests.
- Les traits Mixin sont disponibles pour remplacer davantage les méthodes de cycle de vie des traits de style afin de répondre à des exigences de test spécifiques.
- Vous définissez des classes de test en composant le style de la suite et les traits de mixage.
Comment sélectionner un style de test
ScalaTest propose plusieurs styles de tests, tels que FlatSpec, FunSpec, WordSpec et FunSuite, chacun avec ses avantages et ses inconvénients. Pour les applications Spark, il est important de choisir un style qui équilibre la lisibilité, la flexibilité et la maintenabilité.
Deux styles couramment utilisés sont :
- Suite amusante :
- Simple et direct, FunSuite est idéal pour les développeurs familiarisés avec les frameworks de tests unitaires traditionnels comme JUnit.
- Il fournit une syntaxe concise et permet une organisation facile des tests. C’est un bon choix pour les applications Spark car Spark lui-même a un style de type « FunSuite » pour ses tests.
import org.scalatest.funsuite.AnyFunSuite class MySparkTest extends AnyFunSuite { test(“example test case”) { // Your test code here } }
- Spécification plate :
- FlatSpec propose des noms de tests plus descriptifs, ce qui peut améliorer la lisibilité. C’est un excellent choix lorsque vous souhaitez que vos tests se lisent comme des spécifications.
import org.scalatest.flatspec.AnyFlatSpec class MySparkTest extends AnyFlatSpec{ “A Spark job” should “process data correctly” in { // Your test code here } }
Définir des classes de base
La définition de classes de base pour vos tests peut aider à réduire le code passe-partout et à garantir la cohérence dans votre suite de tests. Une approche courante consiste à créer une classe ou un trait de base qui configure SparkSession/SparkContext et fournit des méthodes utilitaires pour chaque scénario de test.
import org.apache.spark.{SparkConf} import org.apache.spark.sql.{SparkSession, SQLImplicits} import org.scalatest.{BeforeAndAfterAll} import org.scalatest.funsuite.AnyFunSuite trait YourTesthelpers extends AnyFunSuite with BeforeAndAfterAll { self => @transient var ss: SparkSession = null override def beforeAll(): Unit = { super.beforeAll() val sparkConfig = new SparkConf() sparkConfig.set(“spark.master”, “local”) ss = SparkSession.builder().config(sparkConfig).getOrCreate() } override def afterAll(): Unit = { if (ss != null) { ss.stop() } super.afterAll() } }
Avec cette fonctionnalité, tous vos tests auront automatiquement accès à une SparkSession configurée et vous n’aurez pas à répéter la logique de configuration.
En savoir plus: LambdaTest : une plate-forme de test basée sur le cloud et son intégration avec le framework d’automatisation TestNG
Rédaction d’un cas de test
Une fois la classe de base définie, l’écriture d’un scénario de test devient simple. Vous définissez des tests dans des classes qui étendent une classe de style, comme TouteSpécificationFlat. En règle générale, vous étendez une classe de base spécifique à votre projet, qui à son tour étend une classe de style ScalaTest.
Écrivons un test pour une fonction de transformation simple qui filtre les nombres pairs d’un ensemble de données.
test(“filter even numbers from a dataset”) { import ss.implicits._ import org.apache.spark.sql.Dataset val data = Seq(1, 2, 3, 4, 5).toDS() val result: Dataset[Int] = data.filter(_ % 2 == 0) assert(result.collect().sorted === Array(2, 4)) }
Dans cet exemple, nous testons une opération de filtrage simple sur un jeu de données. Nous utilisons la fonction « assert » pour garantir que la transformation fonctionne comme prévu.
Utiliser des assertions
ScalaTest fournit une variété de méthodes d’assertion que vous pouvez utiliser pour vérifier vos résultats. Qui sont utilisés pour vérifier que la sortie réelle de votre code correspond à la sortie attendue. Il existe un large éventail de méthodes d’assertion disponibles pour gérer divers types de comparaisons, telles que l’égalité, l’inégalité et les exceptions.
Voici quelques exemples :
test(“Simple assert”){ val left = 2 val right = 1 assert(left == right) } The detail message in the thrown TestFailedException from this assert will be: “2 did not equal 1”.
test(“Simple assertResult”) val x = 10 val y = 2 assertResult(200) { a * b } In this case, the expected value is 200, and the code being tested is a * b. This assertion will fail, and the detail message in the TestFailedException will read, “Expected 200, but got 20.”
Voici comment vous pouvez affirmer des exceptions ou des erreurs pour garantir que votre tâche Spark gère les cas extrêmes :
test(“Test exception Assert”) { def divide(a: Int, b: Int): Double = { if (b == 0) throw new ArithmeticException("Cannot divide by zero”) a.toDouble / b } val result = assertThrows[ArithmeticException] { divide(10, 0) // This will throw an ArithmeticException } } }
Exécution de tests
L’exécution de tests dans ScalaTest peut être effectuée à l’aide de divers outils, tels que sbt, Maven ou IntelliJ IDEA. Ces outils assurent l’intégration avec ScalaTest et vous permettent d’exécuter des tests à partir de la ligne de commande ou au sein de votre environnement de développement. Par exemple, pour exécuter des tests à l’aide de sbt, vous pouvez utiliser la commande suivante :
sbt test
La commande ci-dessous exécutera tous les cas de test de votre projet. Vous pouvez également exécuter des suites de tests spécifiques en spécifiant le nom de la classe :
sbt “testOnly <TestClassName>”
Tester les applications Scala Spark peut être difficile en raison de leur nature distribuée et de la complexité du traitement des données. Cependant, en choisissant le style de test approprié et en définissant des classes de base réutilisables, vous pouvez garantir que vos applications Spark sont fiables et maintenables.
Avec la quantité de données d’entreprise actuelle, il est nécessaire de disposer d’un partenaire qui vous aide à optimiser, organiser et transformer les données qui vous aident à atteindre vos objectifs commerciaux en les rendant facilement disponibles pour l’analyse et l’action. De la création de pipelines de données au traitement, au stockage et à l’accès aux données traitées, AU NOUVEAUc’est Services d’ingénierie des données vous aider à prendre de meilleures décisions pour créer des plateformes de données et des lacs de données robustes, évolutifs et conformes. Contactez-nous pour plus de détails.
VOUS TROUVEZ CECI UTILE ? PARTAGEZ-LE
Source link