Apache Spark 社区使用各种资源来维护社区测试覆盖率。
GitHub Actions 在 Ubuntu 22.04 上提供以下内容。
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
您需要 -Dtest=none
以避免运行 Java 测试。 有关 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 Serria+ 上使用 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 许可证),并从 Preferences > Plugins
安装 JetBrains Scala 插件。
为 IntelliJ 创建 Spark 项目
File -> Import Project
,找到 Spark 源代码目录,然后选择 “Maven Project”。-P[profile name]
启用的 profile 相同,也可以在导入向导的 Profiles 屏幕上启用。例如,如果为支持 YARN 的 Hadoop 2.7 进行开发,请启用 profile yarn
和 hadoop-2.7
。这些选择可以稍后通过 View 菜单访问 “Maven Projects” 工具窗口并展开 Profiles 部分来更改。其他提示
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* 打开默认的 Remote Configuration 模板:
通常,默认值应该足够使用。确保选择 **Listen to remote JVM** 作为 *Debugger mode* 并选择正确的 JDK 版本以生成正确的 *Command line arguments for remote JVM*。
完成配置并保存后。您可以按照 *Run > Run > Your_Remote_Debug_Name > Debug* 启动远程调试过程并等待 SBT 控制台连接
一般来说,有两个步骤
以下是如何使用 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
进入 Workspace。不要选择 “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 每天都会为 master 和维护分支发布 Maven artifacts 的 SNAPSHOT 版本。 要链接到 SNAPSHOT,您需要将 ASF snapshot 存储库添加到您的构建中。 请注意,SNAPSHOT artifacts 是临时的,可能会更改或删除。 要使用这些,您必须在 https://repository.apache.org/snapshots/ 添加 ASF snapshot 存储库。
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
并添加以下行,配置 Spark JVM 以使用 YourKit 分析代理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 桌面应用程序连接到远程 profiler 代理,您必须在集群的 EC2 安全组中打开这些端口。 为此,请登录到 AWS 管理控制台。 转到 EC2 部分,然后从页面左侧的 Network & Security
部分中选择 Security Groups
。 找到与您的集群相对应的安全组;如果您启动了一个名为 test_cluster
的集群,那么您将需要修改 test_cluster-slaves
和 test_cluster-master
安全组的设置。 对于每个组,从列表中选择它,单击 Inbound
选项卡,然后创建一个新的 Custom TCP Rule
,打开端口范围 10001-10010
。 最后,单击 Apply Rule Changes
。 确保对两个安全组都执行此操作。 注意:默认情况下,spark-ec2
会重复使用安全组:如果您停止此集群并使用相同的名称启动另一个集群,则您的安全组设置将被重用。ec2--.compute-1.amazonaws.com
请参阅完整的 YourKit 文档,以获取 profiler 代理 启动选项的完整列表。
通过 SBT 运行 Spark 测试时,将 javaOptions in Test += "-agentpath:/path/to/yjp"
添加到 SparkBuild.scala
以启用 YourKit profiler 代理启动测试。
特定于平台的分析器代理路径在 YourKit 文档中列出。
一般来说,ASF 允许使用生成式 AI 工具共同创作的贡献。 但是,当您提交包含生成内容的补丁时,需要考虑以下几个方面。
最重要的是,您需要披露此类工具的使用情况。 此外,您有责任确保相关工具的条款和条件与在开源项目中使用兼容,并且包含生成的内容不会造成侵犯版权的风险。
有关详细信息和开发,请参阅 ASF 生成式工具指南。