The solution I came up with is to create an AutoPlugin
for sbt that does what you need.
Create a new file in project
folder named DingPlugin.scala
with following content
import sbt.Keys._
import sbt.PluginTrigger.AllRequirements
import sbt._
object DingPlugin extends AutoPlugin {
private def wavPath = "/path/to/wav"
private def playSound(wav: String) = ???
override def trigger = AllRequirements
override def projectSettings: Seq[Def.Setting[_]] = Seq(
Test / test := (Test / test).andFinally(playSound(wavPath)).value
)
}
The main point is the method andFinally
that
defines a new task that runs the original task and evaluates a side effect regardless of whether the original task succeeded. The result of the task is the result of the original task
The implementation of playSound
is derived from this question with the following code
private def playSound(wav: String): Unit = {
import java.io.BufferedInputStream
import java.io.FileInputStream
import javax.sound.sampled.AudioSystem
val clip = AudioSystem.getClip
val inputStream =
AudioSystem.getAudioInputStream(
new BufferedInputStream(new FileInputStream(wav))
)
clip.open(inputStream)
clip.start()
Thread.sleep(clip.getMicrosecondLength / 1000)
}
Now, you can just run sbt test
and it will play a sound regardless of whether test succeeded or not.