A few weeks ago Daniel Sundman wrote a blog entry about how to test drive JavaScript with Grunt. Today we’ll talk about how to run your Jasmine Grunt setup using Gradle!
There are no standard plugins for Grunt in Gradle, but it’s easy to add all the code manually. After all, this is Gradle not Maven 😉
We’ll assume that node and grunt-cli are already installed see (Test Driving JavaScript with Grunt).
Define an NPM Task
To ensure that all the grunt dependencies are present we’ll add an exec task to Gradle to run npm install. This task needs to be run whenever we make changes to the packages.json file, so we’ll add that as an input. We’ll also specify node_modules as the output directory. To define an Exec task type we need to import org.gradle.api.tasks.Exec, so our build.gradle file will look like this:
import org.gradle.api.tasks.Exec task npm(type: Exec) { group = "Build" description = "Installs all Node.js dependencies defined in package.json" commandLine = ["npm", "install"] inputs.file "package.json" outputs.dir "node_modules" }
Define a GruntTask Type
import org.apache.tools.ant.taskdefs.condition.Os class GruntTask extends Exec { private String gruntExecutable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt" def gruntArgs = ""
public GruntTask() { super() this.setExecutable(gruntExecutable) }
public void setGruntArgs(String gruntArgs) { this.args = "$gruntArgs".trim().split(" ") as List } }
Putting it all together
task jasmine(type: GruntTask) { group = "Verification" description = "Runs the Jasmine tests." gruntArgs = "jasmine" }
Finally we just need to add some depends statements:
jasmine.dependsOn npm check.dependsOn jasmine
Now you can run it from the command line:
gradle jasmine
If you run it again, you’ll notice it executes the tests even though no code has been modified. This is easily fixed by adding inputs to the jasmine task:
task jasmine(type: GruntTask) { group = "Verification" description = "Runs the Jasmine tests." gruntArgs = "jasmine"
inputs.dir "[relative-path-to-source]" inputs.file file("Gruntfile.js")
}
It’s that simple!
Get in touch via my homepage if you have questions or comments!
Very nice!
Improvement:
Collect the output from Grunt to a file.
Show the error output on the console should jasmine fail.
I’ll show how to change the GruntTask to achieve that:
class GruntTask extends Exec {
private String gruntExecutable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt"
def gruntArgs = ""
def output = new ByteArrayOutputStream()
def File outputFile = null
public GruntTask() {
super()
this.setExecutable(gruntExecutable)
// Don't fail immediately after executing the command, we must save the output to a file first...
this.setIgnoreExitValue(true)
// Capture output...
this.setStandardOutput(output)
this.setErrorOutput(output)
}
public void setGruntArgs(String gruntArgs) {
this.args = "$gruntArgs".trim().split(" ") as List
// Construct an output file name with gruntArgs...
def reportsDir = new File(project.buildDir, "reports")
this.outputFile = new File(reportsDir, gruntArgs +".txt")
this.outputs.file outputFile
// After executing command...
this.doLast {
// Save output to a file
output.close()
outputFile.parentFile.mkdirs()
outputFile.text = output.toString()
// Log errors (if any)
def result = getExecResult()
if (result.exitValue != 0) {
logger.error(output.toString())
}
// Fail build if Grunt failed
result.assertNormalExitValue()
}
}
It’s that simple!
(Imagine doing this with Maven…)
Yeah, this is a really nice improvement! Thanks Olle!
Great little tutorial. Works a charm. Thanks for posting
Sure thing! Glad it helped!
How gradle recognizes npm command? I am getting beloe exception from gradle build task
npm’ is not recognized as an internal or external command
Hi, have you installed node.js? You can find the information that you need here: http://nodejs.org/
Yes , I did install Node.js and successfully run npm commends on my windows command prompt.
I am getting npm’ is not recognized as an internal or external command while running through build file (gradle)
it working . Thanks for your earlier replies
I updated my build process task to have below statements to run successful build . if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine = [“cmd”, “/c”, “npm”, “install”] } else { commandLine = [“npm”, “install”] }
Great that you got it working on Windows! Thanks for the update!