codeproject
Jasmine is one of the most popular BDD-style JavaScript testing frameworks. I decided to use it for my new project, Chpokk, built on top of FubuMVC. Here are the steps that I made, together with some for-dummies explanations.
Adding Jasmine to Your Project
This is as easy as adding the FubuMVC.TestRunner
NuGet package to your project. After that, navigate to /testing/suites/whatever, and see a greenish almost empty page that says "0 specs". Jasmine is installed.
What's Under the Hood?
After you add the package, you discover a zip file named fubumvc-testrunner.zip in your fubu-content folder. This file is a "bottle", a piece of functionality that adds itself to the main application. With the first Web request, the zip is extracted ("exploded") to a subfolder. Let's see what we have there.
The WebContent folder is mapped to the root of your application. The Shared subfolder contains the Application.spark file, which is going to be the master page for all test pages, and the bindings file.
Take a look at the following snippet from the Application.spark file:
<Stylesheet href="jasmine.css" />
<Script src="fubumvc-testrunner" />
These tags look unfamiliar. Their meaning is explained in the bindings file:
<element name="Stylesheet">#this.Asset('@href');</element>
<element name="Script">#this.Asset('@src');</element>
this.Asset()
is a method that adds a script/css to the list of assets of the page. Note that it produces no output; in order to write all scripts (together with their dependencies), you have to call:
this.WriteScriptTags()
or, using our bindings, just:
<Scripts />
The actual View is called Run.spark
, and located in the suites folder. It's very simple:
<viewdata model="FubuMVC.TestRunner.Suites.RunSuiteViewModel" />
<content:title>${Model.Suite}</content:title>
<content:scripts>
<Script src="${Model.Suite}" />
</content:scripts>
There are two content areas: one is the page title, the other just adds a script (or a set of scripts, see later) to the page. How do we decide which script to add? We take it from the Url. Because of some model binding magic (plus internal Fubu processing), the last part of the Url is mapped to the Suite
property of the model.
Adding the First Test
In order to use the Fubu's Asset Pipeline, I put my test script into the /Content/scripts folder of my Web.
Here is my sampletest.js:
describe("First test", function() {
it("should fail", function() {
expect(true).toBeFalsy();
});
});
As a real TDD practitioner, I'm creating a failing test first. Mom would be proud of me!
After saving this file, I navigate to /testing/suites/sampletest.js, and I see a failing test. WIN!
Dealing with a Real World Problem
Having all your code in the tests is fine, but at some point a manager might want you to move some of it to the production files. So, we'll need to include several files in our tests. Let's see how to do it.
Let's create another file called realstuff.js, and put it into the Content/Scripts folder:
function arewegood() {
return false;
}
Next, let's create a plain text file, named tests.script.config, and place it in the root of our application. This file will hold our script set definitions. Right now, we'll put the following line there:
tests includes realstuff.js, sampletest.js
Now, we'll use the name of the set in the URL: /testing/suites/tests. If we look at the source, we'll see that both scripts are loaded. We can put another script set in our config file, and we'll be able to run a different suite with a different URL.
The last step is to modify our test so that it depends on the "production" code:
describe("First test", function() {
it("should fail", function() {
expect(arewegood()).toBeTruthy();
});
});
That's it for today, I still have to make this test pass.
Update
@jmarnold pointed me that Serenity does all that and lots of other great stuff. I guess I'll have to delete all this and start from scratch. In the next post, I'll tell you what happened.