Apache Spark 単体テストの戦略


Scala で Apache Spark の単体テストを書くためのレシピ/ガイド (主に初心者向け).


レシピ難易度:◼️◻️◻️◻️
レシピの前提条件:
  • ビッグデータ、Apache Spark、Scala、Java に関するある程度の知識.

  • レシピの材料:
  • お気に入りの IDE : Intellij または VSCode (メタル付き)

  • sbt/maven インストール済み (このチュートリアルでは sbt を使用)
  • jdk 8
  • scala 2.12 😎


  • 単体テスト?
    コンピューター プログラミングでは、ユニット テストは、ソース コードの個々のユニット (1 つまたは複数のコンピューター プログラム モジュールと関連する制御データ、使用手順、および操作手順のセット) をテストして、それらが使用に適しているかどうかを判断するソフトウェア テスト方法です. Wikipedia

    実際のコードを記述する前にコードの単体テストを記述することは、TDD で使用される優れた戦略です.

    TDD ?
    テスト駆動開発 (TDD) は、ソフトウェアが完全に開発される前にソフトウェア要件をテスト ケースに変換し、すべてのテスト ケースに対してソフトウェアを繰り返しテストすることですべてのソフトウェア開発を追跡するソフトウェア開発プロセスです. Wikipedia

    単体テストを作成する利点や TDD の利点については、ここでは省略します (非常に多くのことがあり、別の記事を書く必要があるためです).

    このコード サンプルでは、​​(非常に素晴らしい) Scaltest 😎🤩 テスト フレームワークを使用しています.

    スカラテスト:
  • これは、Scala エコシステムで最も柔軟で最も人気のあるテスト ツールです. link
  • 非常に多くの他の機能により、複数のスタイルでテストを設計できます.
  • ScalaTest は、さまざまなスタイルのテストをサポートしており、それぞれが特定の一連のニーズに対応するように設計されています. link
  • これらのスタイルには個別の特性があります.
  • JUnit 愛好家は AnyFunSuite 特性を使用できます.



  • プロジェクトの作成:
    私のプロジェクトのディレクトリ構造:

    .
    ├── build.sbt
    └── src
        ├── main
        │   └── scala
        │       └── sukumaar
        │           └── App.scala #This doesn't have any imp code
        └── test
            └── scala
                └── sukumaar
                    ├── AppTest.scala
                    └── TraitSparkSessionTest.scala
    

    build.sbt 私が使用したもの:

    name := "sample-spark-scala-project"
    version := "1.0"
    scalaVersion := "2.12.13"
    
    val sparkVersion = "2.4.0"
    
    libraryDependencies += 
        "org.apache.spark" %% "spark-core" % sparkVersion
    libraryDependencies += 
        "org.apache.spark" %% "spark-sql" % sparkVersion
    libraryDependencies += 
        "org.scalatest" %% "scalatest" % "3.2.9" % Test
    
    /*
    // you can always use this dependency if you are 
    // going to use only funsuite
    libraryDependencies += 
        "org.scalatest" %% "scalatest-funsuite" % "3.2.11" % "test"
    */
    


    このプロジェクトをお気に入りの IDE にインポートします.
    (成熟した開発者のように)CLI を好む場合は、sbt clean compile と入力してください

    私が従った手順:
    もちろん、パッケージ名を変更できます.その場合は、前の手順でそれに応じてディレクトリ名を変更する必要があります

    ステップ 1: これを TraitSparkSessionTest.scala に追加します

    package sukumaar
    trait TraitSparkSessionTest {}
    


    ステップ 2: これを TraitSparkSessionTest.scala に追加します

    package sukumaar
    
    import org.apache.spark.sql.SparkSession
    
    trait TraitSparkSessionTest {
    
      protected val sparkSession = SparkSession
        .builder()
        .appName("sample-spark-scala-project")
        .master("local[2]")
        .getOrCreate()       
    }
    


    ステップ 3: これを AppTest.scala に追加します

    package sukumaar
    class AppTest {}
    


    秘訣は、sparkSession オブジェクトは、複数の Spark セッションを使用するユース ケースがない限り、spark テスト ケースが存在するすべてのテスト クラスで使用する必要があることです.
    このオブジェクトは TraitSparkSessionTest トレイトの一部であるため、このトレイトはミックスインとして簡単に使用でき、テスト クラスと混合できます.

    ステップ 4: これを AppTest.scala に追加します

    package sukumaar
    import org.scalatest.funsuite.AnyFunSuite
    
    class AppTest extends AnyFunSuite 
    with TraitSparkSessionTest //<-this is the same trait having sparkSession
    {
    
      import sparkSession.implicits._ 
      // this will enable methods like toDF() to DS
    
      test("this is sample test") {
    
        val rdd = sparkSession
        .sparkContext
        .parallelize(Seq("A", "B"))
    
        val ds = rdd.toDS
        ds.show() 
        //for sake of debugging, otherwise it should be avoided
    
        ds.cache()
        /*
        ds.cache()  not required if action operation on 
        dataset/dataframe is getting performed only once
        but otherwise
        */
    
        assert(2 == ds.count()) // assertion
      }
    }
    
    


    終わり.さあ、テストを実行しましょう 😇

    完全なソース コード リンク: https://github.com/sukumaar/spark-scala-unit-test-example



    s/w versions used:
    jdk 1.8.0_312 
    scala 2.12.15
    sbt 1.6.2
    os: ubuntu 20.04.4 lts