讓我們來談談測試。一旦你編寫了一個插件,它就會變成一個長期的項目。為了持續添加新功能(或持續修復錯誤),編寫測試是合理的。
sbt 附帶了腳本化測試框架,可讓你編寫建置情境的腳本。它被編寫用於在複雜情境下測試 sbt 本身 — 例如變更偵測和部分編譯
現在,考慮一下,如果你刪除 B.scala 但不更新 A.scala 會發生什麼。當你重新編譯時,應該會收到錯誤,因為 B 不再存在供 A 參考。[…(非常複雜的東西)]
腳本化測試框架用於驗證 sbt 是否能處理如上所述的情況。
該框架透過 scripted-plugin 提供。本頁的其餘部分將說明如何將 scripted-plugin 包含到你的插件中。
在你開始之前,將你的版本設定為 **-SNAPSHOT** 版本,因為 scripted-plugin 會在本地發佈你的插件。如果你不使用 SNAPSHOT,你可能會陷入你和世界其他地方看到不同成品的可怕不一致狀態。
在 build.sbt
中啟用 SbtPlugin
lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
.settings(
name := "sbt-something"
)
然後將以下設定新增至 build.sbt
lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
.settings(
name := "sbt-something",
scriptedLaunchOpts := { scriptedLaunchOpts.value ++
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
},
scriptedBufferLog := false
)
注意:你必須使用 sbt 1.2.1 及以上版本才能使用 SbtPlugin
。
建立目錄結構 src/sbt-test/<測試群組>/<測試名稱>
。首先,嘗試類似 src/sbt-test/<你的插件名稱>/simple
的東西。
準備好了嗎?在 simple
中建立初始建置。就像使用你的插件的真實建置一樣。我相信你已經有幾個可以手動測試的建置了。以下是一個 build.sbt
的範例
lazy val root = (project in file("."))
.settings(
version := "0.1",
scalaVersion := "2.10.6",
assembly / assemblyJarName := "foo.jar"
)
在 project/plugins.sbt
中
sys.props.get("plugin.version") match {
case Some(x) => addSbtPlugin("com.eed3si9n" % "sbt-assembly" % x)
case _ => sys.error("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
}
這是我從 earldouglas/xsbt-web-plugin@feabb2 中學到的技巧,它允許我們將版本號碼傳遞到測試中。
我還有 src/main/scala/hello.scala
object Main {
def main(args: Array[String]): Unit = {
println("hello")
}
}
現在,編寫一個腳本,在位於測試專案根目錄的稱為 test
的檔案中描述你的情境。
# check if the file gets created
> assembly
$ exists target/scala-2.10/foo.jar
以下是腳本的語法
#
開始單行註解>
name
將任務傳送到 sbt(並測試是否成功)$
name arg*
執行檔案命令(並測試是否成功)->
name
將任務傳送到 sbt,但預期它會失敗-$
name arg*
執行檔案命令,但預期它會失敗檔案命令有
touch
path+
建立或更新檔案的時間戳記delete
path+
刪除檔案exists
path+
檢查檔案是否存在mkdir
path+
建立目錄absent
path+
檢查檔案是否不存在newer
source target
檢查 source
是否較新must-mirror
source target
檢查 source
是否相同pause
暫停直到按下 Enter 鍵sleep
time
睡眠(以毫秒為單位)exec
command args*
在另一個進程中執行命令copy-file
fromPath toPath
複製檔案copy
fromPath+ toDir
將路徑複製到 toDir
,保留相對結構copy-flat
fromPath+ toDir
將路徑複製到 toDir
平面化因此,我的腳本將執行 assembly
任務,並檢查是否建立 foo.jar
。我們稍後將介紹更複雜的測試。
若要執行腳本,請返回你的插件專案,然後執行
> scripted
這會將你的測試建置複製到暫時目錄中,並執行 test
腳本。如果一切順利,你會看到 publishLocal
正在執行,然後
Running sbt-assembly / simple
[success] Total time: 18 s, completed Sep 17, 2011 3:00:58 AM
檔案命令很棒,但遠遠不夠,因為它們都無法測試實際內容。測試內容的簡單方法是在你的測試建置中實作自訂任務。
對於我的 hello 專案,我想檢查產生的 jar 是否會列印出「hello」。我可以利用 scala.sys.process.Process
來執行 jar。若要表達失敗,只需拋出錯誤。以下是 build.sbt
import scala.sys.process.Process
lazy val root = (project in file("."))
.settings(
version := "0.1",
scalaVersion := "2.10.6",
assembly / assemblyJarName := "foo.jar",
TaskKey[Unit]("check") := {
val process = Process("java", Seq("-jar", (crossTarget.value / "foo.jar").toString))
val out = (process!!)
if (out.trim != "bye") sys.error("unexpected output: " + out)
()
}
)
我故意測試它是否與「bye」匹配,以查看測試如何失敗。
以下是 test
# check if the file gets created
> assembly
$ exists target/foo.jar
# check if it says hello
> check
執行 scripted
會如預期般讓測試失敗
[info] [error] {file:/private/var/folders/Ab/AbC1EFghIj4LMNOPqrStUV+++XX/-Tmp-/sbt_cdd1b3c4/simple/}default-0314bd/*:check: unexpected output: hello
[info] [error] Total time: 0 s, completed Sep 21, 2011 8:43:03 PM
[error] x sbt-assembly / simple
[error] {line 6} Command failed: check failed
[error] {file:/Users/foo/work/sbt-assembly/}default-373f46/*:scripted: sbt-assembly / simple failed
[error] Total time: 14 s, completed Sep 21, 2011 8:00:00 PM
在你掌握它之前,測試本身可能需要一段時間才能正確運作。有幾種技術可能會派上用場。
首先要開始的地方是關閉日誌緩衝。
> set scriptedBufferLog := false
例如,這應該會列印出暫時目錄的位置
[info] [info] Set current project to default-c6500b (in build file:/private/var/folders/Ab/AbC1EFghIj4LMNOPqrStUV+++XX/-Tmp-/sbt_8d950687/simple/project/plugins/)
...
將以下行新增至你的 test
腳本,以暫停測試直到你按下 Enter 鍵
$ pause
如果你正在考慮進入 sbt/sbt-test/sbt-foo/simple
並執行 sbt
,請不要這麼做。正確的方法是將目錄複製到其他地方並執行它。
在 sbt 專案本身下,實際上還有 100 多個腳本化測試。瀏覽一下以獲得靈感。
例如,以下是名為 by-name 的測試。
> compile
# change => Int to Function0
$ copy-file changes/A.scala A.scala
# Both A.scala and B.scala need to be recompiled because the type has changed
-> compile
xsbt-web-plugin 和 sbt-assembly 也有一些腳本化測試。
就是這樣!請告訴我您測試插件的經驗!