Apache Sparkコミュニティは、コミュニティのテストカバレッジを維持するためにさまざまなリソースを使用しています。
GitHub Actionsは、Ubuntu 22.04で以下を提供します。
AppVeyorは、Windowsで以下を提供します。
Scalewayは、MacOSおよびApple Siliconで以下を提供します。
Sparkのデフォルトのビルド戦略は、すべての依存関係を含むjarをアセンブルすることです。これは、反復開発を行う際に煩雑になる可能性があります。ローカルで開発する場合、Sparkのすべての依存関係を含むアセンブリjarを作成し、変更を加える際にSpark自体のみを再パッケージ化することができます。
$ build/sbt clean package
$ ./bin/spark-shell
$ export SPARK_PREPEND_CLASSES=true
$ ./bin/spark-shell # Now it's using compiled classes
# ... do some local development ... #
$ build/sbt compile
$ unset SPARK_PREPEND_CLASSES
$ ./bin/spark-shell
# You can also use ~ to let sbt do incremental builds on file changes without running a new sbt session every time
$ build/sbt ~compile
たとえば、Spark Coreモジュールは、次のようにビルドできます。
$ # sbt
$ build/sbt
> project core
> package
$ # or you can build the spark-core module with sbt directly using:
$ build/sbt core/package
$ # Maven
$ build/mvn package -DskipTests -pl core
ローカルで開発する場合、テストスイート全体を実行するのではなく、単一のテストまたは少数のテストを実行すると便利なことがよくあります。
個々のテストを実行する最速の方法は、sbt
コンソールを使用することです。sbt
コンソールを開いたままにして、必要に応じてテストを再実行するために使用するのが最速です。たとえば、特定のプロジェクト(例:core
)のすべてのテストを実行するには、次のようにします。
$ build/sbt
> project core
> test
testOnly
コマンドを使用して、単一のテストスイートを実行できます。たとえば、DAGSchedulerSuiteを実行するには、次のようにします。
> testOnly org.apache.spark.scheduler.DAGSchedulerSuite
testOnly
コマンドはワイルドカードを受け入れます。たとえば、DAGSchedulerSuite
を次のように実行することもできます。
> testOnly *DAGSchedulerSuite
または、スケジューラパッケージのすべてのテストを実行することもできます。
> testOnly org.apache.spark.scheduler.*
DAGSchedulerSuite
の単一のテスト(たとえば、名前に「SPARK-12345」を含むテスト)を実行する場合は、sbtコンソールで次のコマンドを実行します。
> testOnly *DAGSchedulerSuite -- -z "SPARK-12345"
必要に応じて、これらすべてのコマンドをコマンドラインで実行できます(ただし、これは開いているコンソールを使用してテストを実行するよりも遅くなります)。これを行うには、testOnly
とそれに続く引数を引用符で囲む必要があります。
$ build/sbt "core/testOnly *DAGSchedulerSuite -- -z SPARK-12345"
sbtで個々のテストを実行する方法の詳細については、sbtドキュメントを参照してください。
Mavenでは、-DwildcardSuites
フラグを使用して個々のScalaテストを実行できます。
build/mvn -Dtest=none -DwildcardSuites=org.apache.spark.scheduler.DAGSchedulerSuite test
Javaテストを実行しないようにするには、-Dtest=none
が必要です。ScalaTest Mavenプラグインの詳細については、ScalaTestドキュメントを参照してください。
個々のJavaテストを実行するには、-Dtest
フラグを使用できます。
build/mvn test -DwildcardSuites=none -Dtest=org.apache.spark.streaming.JavaAPISuite test
個々のPySparkテストを実行するには、python
ディレクトリの下にあるrun-tests
スクリプトを使用できます。テストケースは、各PySparkパッケージの下のtests
パッケージにあります。なお、Apache SparkのScala側またはPython側に変更を加えた場合は、変更を適用するためにPySparkテストを実行する前に、Apache Sparkをもう一度手動でビルドする必要があります。PySparkテストスクリプトを実行しても、自動的にビルドされません。
また、macOS High Sierra +でPySparkを使用するには、現在進行中の問題があります。一部のテストを実行するには、OBJC_DISABLE_INITIALIZE_FORK_SAFETY
をYES
に設定する必要があります。詳細については、PySparkの問題とPythonの問題を参照してください。
特定のモジュールでテストケースを実行するには
$ python/run-tests --testnames pyspark.sql.tests.test_arrow
特定のクラスでテストケースを実行するには
$ python/run-tests --testnames 'pyspark.sql.tests.test_arrow ArrowTests'
特定のクラスで単一のテストケースを実行するには
$ python/run-tests --testnames 'pyspark.sql.tests.test_arrow ArrowTests.test_null_conversion'
特定のモジュールでdoctestを実行することもできます。
$ python/run-tests --testnames pyspark.sql.dataframe
最後に、同じ場所にrun-tests-with-coverage
という別のスクリプトがあり、PySparkテストのカバレッジレポートを生成します。run-tests
と同じ引数を受け入れます。
$ python/run-tests-with-coverage --testnames pyspark.sql.tests.test_arrow --python-executables=python
...
Name Stmts Miss Branch BrPart Cover
-------------------------------------------------------------------
pyspark/__init__.py 42 4 8 2 84%
pyspark/_globals.py 16 3 4 2 75%
...
Generating HTML files for PySpark coverage under /.../spark/python/test_coverage/htmlcov
/.../spark/python/test_coverage/htmlcov
の下にあるHTMLで、カバレッジレポートを視覚的に確認できます。
python/run-tests[-with-coverage] --help
で他の利用可能なオプションを確認してください。
GitHub ActionsはK8sユニットテストと統合テストのカバレッジの両方を提供しますが、ローカルで実行することもできます。たとえば、Volcanoバッチスケジューラ統合テストは手動で行う必要があります。詳細については、統合テストのドキュメントを参照してください。
https://github.com/apache/spark/blob/master/resource-managers/kubernetes/integration-tests/README.md
Docker統合テストはGitHub Actionsによってカバーされています。ただし、開発とテストを高速化するためにローカルで実行することもできます。詳細については、Docker統合テストのドキュメントを参照してください。
Apache Sparkは、継続的インテグレーションと幅広い自動化を可能にするGitHub Actionsを活用しています。Apache Sparkリポジトリは、開発者がプルリクエストを作成する前に実行するためのいくつかのGitHub Actionsワークフローを提供しています。
Apache Sparkリポジトリは、GitHub Actionsでベンチマークを実行するための簡単な方法を提供しています。プルリクエストでベンチマーク結果を更新する場合は、可能な限り同じ環境で実行するために、GitHub Actionsを使用してベンチマーク結果を実行および生成することをお勧めします。
org.apache.spark.sql.*
です。11
です。true
の場合、すぐに失敗します。false
の場合、失敗してもすべて実行されます。ScalaTestを実行するときに次のエラーが発生した場合
An internal error occurred during: "Launching XYZSuite.scala".
java.lang.NullPointerException
これは、クラスパスに正しくないScalaライブラリがあるためです。修正するには
Build Path | Configure Build Path
を選択します。Add Library | Scala Library
scala-library-2.10.4.jar - lib_managed\jars
を削除します。「Could not find resource path for Web UI: org/apache/spark/ui/static」が発生した場合は、クラスパスの問題が原因です(一部のクラスがコンパイルされていない可能性があります)。これを修正するには、コマンドラインからテストを実行すれば十分です。
build/sbt "testOnly org.apache.spark.rdd.SortingSuite"
バイナリ互換性を確保するために、SparkはMiMaを使用しています。
問題に取り組んでいるときは、プルリクエストを開く前に、変更によってバイナリ非互換性が導入されていないことを確認することをお勧めします。
次のコマンドを実行することで、これを行うことができます。
$ dev/mima
MiMaによって報告されたバイナリ非互換性は、次のようになります。
[error] method this(org.apache.spark.sql.Dataset)Unit in class org.apache.spark.SomeClass does not have a correspondent in current version
[error] filter with: ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.spark.SomeClass.this")
バイナリ非互換性が正当化されると考えられる場合、またはMiMaが誤検出を報告した場合(たとえば、報告されたバイナリ非互換性がユーザー向けではないAPIに関する場合)、project/MimaExcludes.scalaに除外を追加することでフィルタリングできます。除外には、MiMaレポートで示唆された内容と、作業中の問題のJIRA番号とそのタイトルを含むコメントが含まれている必要があります。
上記の問題については、次を追加することができます。
// [SPARK-zz][CORE] Fix an issue
ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.spark.SomeClass.this")
それ以外の場合、プルリクエストを開いたり更新したりする前に、これらの非互換性を解決する必要があります。通常、MiMaによって報告される問題は自明であり、バイナリ互換性を維持するために追加する必要がある、欠落しているメンバー(メソッドまたはフィールド)に関するものです。
Gitは、リモートプルリクエストを独自のローカルリポジトリにフェッチするためのメカニズムを提供します。これは、コードを確認したり、パッチをローカルでテストしたりする場合に役立ちます。Spark Gitリポジトリをまだ複製していない場合は、次のコマンドを使用します。
$ git clone https://github.com/apache/spark.git
$ cd spark
この機能を有効にするには、プルリクエストデータをフェッチするようにgitリモートリポジトリを設定する必要があります。これを行うには、Sparkディレクトリ内にある.git/config
ファイルを修正します。別の名前を付けた場合、リモートの名前は「origin」ではない場合があります。
[remote "origin"]
url = git@github.com:apache/spark.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/pull/*/head:refs/remotes/origin/pr/* # Add this line
これが完了したら、リモートプルリクエストをフェッチできます。
# Fetch remote pull requests
$ git fetch origin
# Checkout a remote pull request
$ git checkout origin/pr/112
# Create a local branch from a remote pull request
$ git checkout origin/pr/112 -b new-branch
$ # sbt
$ build/sbt dependencyTree
$ # Maven
$ build/mvn -DskipTests install
$ build/mvn dependency:tree
Aaron DavidsonのIntelliJ Imports Organizerを使用して、コード内のインポートを整理できます。スタイルガイドのインポート順序と一致するように設定できます。
Scalaコードをフォーマットするには、PRを送信する前に次のコマンドを実行します。
$ ./dev/scalafmt
デフォルトでは、このスクリプトはgit masterと異なるファイルをフォーマットします。詳細については、scalafmtドキュメントを参照してください。ただし、ローカルにインストールされたバージョンのscalafmtではなく、既存のスクリプトを使用してください。
多くのSpark開発者はコマンドラインでSBTまたはMavenを使用していますが、最も一般的に使用されているIDEはIntelliJ IDEAです。コミュニティ版は無料で入手でき(ApacheコミッターはIntelliJ Ultimate Editionのライセンスを無料で入手できます)、JetBrains ScalaプラグインはPreferences > Plugins
からインストールできます。
IntelliJでSparkプロジェクトを作成するには
File -> Import Project
に移動し、Sparkのソースディレクトリを見つけて、「Maven Project」を選択します。-P[profile name]
で有効にしたものと同じプロファイルを、インポートウィザードのプロファイル画面で有効にすることができます。たとえば、YARNをサポートするHadoop 2.7向けに開発する場合は、プロファイルyarn
とhadoop-2.7
を有効にします。これらの選択は、後で[表示]メニューから[Maven Projects]ツールウィンドウにアクセスし、[プロファイル]セクションを展開することで変更できます。その他のヒント
Preference -> Build, Execution, Deployment -> Maven -> Maven home directory
)を、より新しいMavenインストールを指すようにリセットしてください。また、スクリプトbuild/mvn
を使用して最初にSparkをビルドすることもできます。スクリプトが十分に新しいMavenインストールを見つけられない場合は、最新バージョンのMavenをbuild/apache-maven-<version>/
フォルダにダウンロードしてインストールします。/Users/irashid/github/spark/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala
Error:(147, 9) value q is not a member of StringContext
Note: implicit class Evaluate2 is not applicable here because it comes after the application point and it lacks an explicit result type
q"""
^
このパートでは、IntelliJを使用してSparkをリモートでデバッグする方法を説明します。
Run > Edit Configurations > + > Remoteに従って、デフォルトのリモート構成テンプレートを開きます:
通常、デフォルト値で十分です。Debugger modeとしてListen to remote JVMを選択し、適切なJDKバージョンを選択して、適切なCommand line arguments for remote JVMを生成してください。
構成を完了して保存したら、Run > Run > Your_Remote_Debug_Name > Debugに従ってリモートデバッグプロセスを開始し、SBTコンソールが接続するのを待ちます。
一般的に、2つの手順があります。
以下は、SBT単体テストを使用してリモートデバッグをトリガーする方法の例です。
SBTコンソールに入力します
./build/sbt
ターゲットテストがあるプロジェクトに切り替えます。例:
sbt > project core
Command line arguments for remote JVMをコピーして貼り付けます
sbt > set javaOptions in Test += "-agentlib:jdwp=transport=dt_socket,server=n,suspend=n,address=localhost:5005"
IntelliJでブレークポイントを設定し、SBTでテストを実行します。例:
sbt > testOnly *SparkContextSuite -- -t "Only one SparkContext may be active at a time"
IntelliJコンソールに「Connected to the target VM, address: 'localhost:5005', transport: 'socket'」と表示されたら、IntelliJに正常に接続されています。その後、通常どおりIntelliJでデバッグを開始できます。
リモートデバッグモードを終了するには(リモートデバッガを起動し続ける必要がないように)、プロジェクトにいる間にSBTコンソールに「session clear」と入力します。
Eclipseを使用してSparkを開発およびテストできます。以下の構成は動作することが知られています。
最も簡単な方法は、Scala IDEのダウンロードページからScala IDEバンドルをダウンロードすることです。ScalaTestがプリインストールされています。または、Scala IDEアップデートサイトまたはEclipse Marketplaceを使用します。
SBTは、Eclipseの.project
ファイルと.classpath
ファイルを作成できます。Sparkの各サブプロジェクトにこれらのファイルを作成するには、次のコマンドを使用します。
sbt/sbt eclipse
特定のプロジェクト(例:spark-core)をインポートするには、File | Import | Existing Projects
を選択してワークスペースにインポートします。「Copy projects into workspace」は選択しないでください。
Scala 2.10で開発する場合は、Sparkのコンパイルに使用されるScalaバージョンとまったく同じScalaインストールを構成する必要があります。Scala IDEは最新バージョン(現時点では2.10.5と2.11.8)をバンドルしているため、Eclipse Preferences -> Scala -> Installations
で、Scala 2.10.5ディストリビューションのlib/
ディレクトリを指すことで追加する必要があります。これが完了したら、すべてのSparkプロジェクトを選択して右クリックし、Scala -> Set Scala Installation
を選択して、2.10.5インストールを指します。これにより、無効なクロスコンパイルライブラリに関するすべてのエラーが解消されます。これでクリーンビルドが成功するはずです。
ScalaTestは、ソースファイルを右クリックしてRun As | Scala Test
を選択することで、単体テストを実行できます。
Javaメモリエラーが発生した場合は、Eclipseインストールディレクトリのeclipse.ini
の設定を増やす必要がある場合があります。必要に応じて、次の設定を増やします。
--launcher.XXMaxPermSize
256M
Sparkは、マスターブランチとメンテナンスブランチの両方について、MavenアーティファクトのSNAPSHOTリリースを毎晩公開しています。SNAPSHOTにリンクするには、ASFスナップショットリポジトリをビルドに追加する必要があります。SNAPSHOTアーティファクトは一時的なものであり、変更または削除される可能性があることに注意してください。これらを使用するには、https://repository.apache.org/snapshots/にあるASFスナップショットリポジトリを追加する必要があります。
groupId: org.apache.spark
artifactId: spark-core_2.12
version: 3.0.0-SNAPSHOT
YourKit Java Profilerを使用してSparkアプリケーションをプロファイリングする手順を以下に示します。
/root
):unzip YourKit-JavaProfiler-2017.02-b66.zip
~/spark-ec2/copy-dir /root/YourKit-JavaProfiler-2017.02
~/spark/conf/spark-env.sh
を編集し、次の行を追加して、YourKitプロファイリングエージェントを使用するようにSpark JVMを構成します。SPARK_DAEMON_JAVA_OPTS+=" -agentpath:/root/YourKit-JavaProfiler-2017.02/bin/linux-x86-64/libyjpagent.so=sampling"
export SPARK_DAEMON_JAVA_OPTS
SPARK_EXECUTOR_OPTS+=" -agentpath:/root/YourKit-JavaProfiler-2017.02/bin/linux-x86-64/libyjpagent.so=sampling"
export SPARK_EXECUTOR_OPTS
~/spark-ec2/copy-dir ~/spark/conf/spark-env.sh
~/spark/bin/stop-all.sh
および~/spark/bin/start-all.sh
10001-10010
を使用します。YourKitデスクトップアプリケーションをリモートプロファイラエージェントに接続するには、クラスタのEC2セキュリティグループでこれらのポートを開く必要があります。これを行うには、AWSマネジメントコンソールにサインインします。EC2セクションに移動し、ページ左側のネットワークとセキュリティ
セクションからセキュリティグループ
を選択します。クラスタに対応するセキュリティグループを見つけます。test_cluster
という名前のクラスタを起動した場合、test_cluster-slaves
およびtest_cluster-master
セキュリティグループの設定を変更する必要があります。各グループについて、リストから選択し、受信
タブをクリックして、ポート範囲10001-10010
を開く新しいカスタムTCPルール
を作成します。最後に、ルールの変更を適用
をクリックします。両方のセキュリティグループに対してこれを実行してください。注:デフォルトでは、spark-ec2
はセキュリティグループを再利用します。このクラスタを停止して同じ名前の別のクラスタを起動すると、セキュリティグループの設定が再利用されます。ec2--.compute-1.amazonaws.com
)を入力します。プロファイラエージェントの起動オプションの完全なリストについては、YourKitのドキュメント全体を参照してください。
SBTを介してSparkテストを実行する場合、YourKitプロファイラエージェントを有効にしてテストを起動するには、SparkBuild.scala
にjavaOptions in Test += "-agentpath:/path/to/yjp"
を追加します。
プロファイラエージェントへのプラットフォーム固有のパスは、YourKitドキュメントに記載されています。
一般的に、ASFは生成AIツールを使用して共同執筆されたコントリビューションを許可します。ただし、生成されたコンテンツを含むパッチを送信する際には、いくつかの考慮事項があります。
まず、そのようなツールの使用を開示する必要があります。さらに、問題のツールの利用規約がオープンソースプロジェクトでの使用と互換性があり、生成されたコンテンツを含めることで著作権侵害のリスクが生じないことを確認する責任があります。
詳細と開発については、ASF生成ツールガイダンスを参照してください。