Monday, 5 September 2011

Unit testing of javascript in MVC 3 application

Goal: Unit testing the javascript code
In todays modern web applications, unit testing all your layers should be a goal. Often a developer unit tests the C#-code, so why only write unit tests for the server code, when the client code (such as javascript) is just as important? The end user uses both, and if there are custom logic in your javascript the code should definately have its own unit tests. In this article I will explain my own little adventure into looking at the possibilities I have to unit test my javascript code.

Initial spin
I have trying to resolve the issue of how to proper unit test javascript code in a MVC application the latest days. Basically I initially started out with the idea of definining which javascript code I would like to load and which unit test I would like to run. I ended up creating a test solution which was essentially working, but I did not like the end result. The good part was that I was using the QUnit unit testing framework that much of jQuery is based upon. I basically wrote the necessary code to define the javascript and the unit tests to run and I then looped through the list to launch off the browser to display results from QUnit. Yes, this works and yes it uses the elegant QUnit framework - but there are several negative sides of this browser launcher approach. The really negative part is that these browser launched tests needs non-automatic supervision. The tester must inspect the results in the browser and there is really a lot of dependendency going on. We need a working browser and web server, so this is not a general unit test. I was striving to find the solution, and in general I wanted to use MS Test, i.e. I wanted to define ordinary unit tests that were "javascript flavored". Before venturing too deep into this seemingly mess, I discovered that somebody else already had thought of this.

Stephen Walter to the rescue
In his blog article, Stephen Walter explains how to do the proper unit test
with MsTest, which is just what I wanted. Best of all, since we now can use MsTest this will support automatic running of unit tests and fits nicely into MSBuild and the rest of the test infrastructure. Finally the javascript code can be put under control! What I then did was read through Stephen Walter's article and test out his complementary solution. It worked perfectly out of the box, and I do not see much changes that needs to be done to make this suit perfect into MVC 3 as Stephen Walter already shows the solution in such an application.

Summing up the article of Steven Walter
I just want to confirm to the rest of the interested party that Steven Walter's solution to unit tests in javascript is working perfectly. I will present his solution in summary form next. First of all, the unit test project added to the MVC
project that should have tests for javascript must have a reference to the Microsoft Script Control. This is an ActiveX COM component. The addon can be downloaded using the link next: Microsoft Script Control 1.0. Once this DLL has been added to the unit test project, you want to add a unit test. This will not be a basic unit test, as this kind of test does not have a TestContext, which will be needed. Second, add a folder called helpers, and add Stephen Walter's helper class for running the javascript code. The javascript code and javascript unit test will not run in a browser envrironment, but use the ScriptControl class. This will behind the scenes actually use the JScript engine which means that the browser in effect we test is Internet Explorer 8. This will actually suit our needs, since the loading of the additional libraries such as jQuery to support cross browser support should also be needed. The plumbing code to set up the ScriptControl with the correct .js library files I would suggest is set up in the TestInitialize method of your unit test, and it should call a common method, preferably also in Helpers folder to load up the "default" jquery javascript files once javascript code that uses jQueryis to be tested. Beware of the ordering of loading the js files. The js files should be as default be built using build type content (we will load up these files using "loose files"). The path pointing to the js files should point to the javascript files in the Content/Scripts folder. In general, javascript that should be tested and be available for the views should in general reside in the Content/Scripts folder for a MVC application. The tests written in javascript is in Steven Walters example put in a folder called JavascriptTests in the test project. This looks like a good practice. In general, the folder structure under Content/Scripts should somehow match the folder structure under JavascriptTests, once one gets more javascript tests added.

In Steven Walther's article there is a specific step of setting up the test settings for the javascript code to deploy a folder for the javascript code during the execution of the test. This step should be carefully read, since the tests needs to find the javascript files during the testexecution. Basically, a .testsetting file needs to be added to the solution to make this possible, so I just refer to the article.

Let me present the helper class which Steven Walter created for instantiating and initializing the ScriptControl instance.



public class JavaScriptTestHelper : IDisposable {

private ScriptControl _sc;
private TestContext _context;

///
/// You need to use this helper with Unit Tests and not
/// Basic Unit Tests because you need a Test Context
///

/// Unit Test Test Context
public JavaScriptTestHelper(TestContext testContext) {
if (testContext == null) {
throw new ArgumentNullException("TestContext");
}
_context = testContext;

_sc = new ScriptControl();
_sc.Language = "JScript";
_sc.AllowUI = false;
}

///
/// Load the contents of a JavaScript file into the
/// Script Engine.
///

/// Path to JavaScript file
public void LoadFile(string path) {
var fileContents = File.ReadAllText(path);
_sc.AddCode(fileContents);
}

///
/// Pass the path of the test that you want to execute.
///

/// JavaScript function name
public void ExecuteTest(string testMethodName) {
dynamic result = null;
try {
result = _sc.Run(testMethodName, new object[] { });
} catch {
var error = ((IScriptControl)_sc).Error;
if (error != null) {
var description = error.Description;
var line = error.Line;
var column = error.Column;
var text = error.Text;
var source = error.Source;
if (_context != null) {
var details = String.Format("{0} \r\nLine: {1} Column: {2}", source, line, column);
_context.WriteLine(details);
}
}
throw new AssertFailedException(error.Description);
}
}

public void Dispose() {
_sc = null;
}



The JavascriptTestHelper class of Steven Walter basically news up a ScriptControl class and contains two methods to load a javscript file (.js) and then exceute the test. Of course, several javascript files can be added. Note that the ScriptControl instance which is a COM object needs to be nulled when disposing the object.

Ok, so this is the class that will be used when writing the [TestMethod] in C# for the javascript test. Basically we must arrange the test using this testhelper to load up the .js files, and then use the test helper to execute the javascript test. The test method name must be added also to the ScriptController instance before starting up.

Every javascript unit test will of course in essence be written in Javascript, the C# based unit test is just a wrapper, the really interesting part is as always in Javscript when it comes to the client code. So each javascript class will then refer to a utility library. Steven Walther gives a very simple example of such a library, which is nothing more than providing a AreEqual function. The unit test written in javascript will then refer to this "library", using the ///
syntax. This library will be in the base path of he JavascriptTests folder for now. The path must point to this JavascriptUnitTestLibrary.js file. The AreEqual method is really simple and the addition of more methods to support different errors should be a overcoming task. I will myself try out addind more such methods. The sad part is that this code does not use QUnit to support more function that Steven Walter's AreEqual metod, but this method covers very much of the needed functionality. I will soon add more examples of unit testing functions soon into this file.

Here is the JavascriptUnitTestLibrary.js file:

var assert = {

areEqual: function (expected, actual, message) {
if (expected !== actual) {
throw new Error("Expected value " + expected
+ " is not equal to " + actual + ". " + message);
}
}

};

The little library does nothing more than define an object with a single method areEqual which will throw an error. The script controller will in the helper class
catch this error and then rethrow it into an AssertFailedException, which MSTest will then recognize and we are getting our fancy detection of errors in Javascript that MSTest will see! Elegant!

So the only thing next when it comes to the javascript unit test is to write the test and use this utility library. Lets add a new test for demonstrational purposes to the addTwoNumbers method Steven Walther was presenting in this article, the factorial of a number, let's put this additional code to MathTest.js (the reference line at the top should only be listed once).

MathTest.js:

///
function testFactorial() {
var result = factorial(5);
assert.areEqual(120, result, "factorial did not return righ value!");
}

This test will then assert that the factorial of five is equal to 120 (check with your calculator!). The MathTest.js file is added to the JavascriptTests folder.

Ok, so next up is then writing the unit test, add a new unit test to the test project
and then write the following:

[TestMethod]
public void TestFactorial()
{
var jsHelper = new JavaScriptTestHelper(this.TestContext);
jsHelper.LoadFile("JavaScriptUnitTestFramework.js");
jsHelper.LoadFile(@"..\..\..\MvcApplication1\Scripts\Math.js");
jsHelper.LoadFile("MathTest.js");
jsHelper.ExecuteTest("testFactorial");
}

If you can't understand why the code in the JavascriptTests are references as seemingly being in the same folder as the unit test (which is one folder up), this is handled by the testsettings file added previously. Refer to Steven Walthers article.

The test method in my file, UnitTest1.cs is then newing up the test helper class
and make note, passes in the testcontext of my unit test, which is why a basic unit
test will not suffice in this case. Then the ordering of loading the js files is
important. First the unit test framework js file is added. Then the javascript
code is added which will be tested. Next up the javascript code that contains the
javascript based test is added. If your javascript code uses a lot of jQuery libraries, additional js files should be added before the user provided javascript
code. The ordering is as previously mentioned important, and the paths should be correct. Basically one wants to go up three levels of the current directory and then go into the Scripts or Content/Scripts folder to the target .js file. I really suggest that the Scripts folder should be the place that custom javascript is added and that the .js files that the user creates should be in sub folders here. The base directory of the Scripts folder should only contain the jquery libraries and similar, not the user based code, as this is not very scalable as the web project grows..

Finally the ExecuteTest is called and the parameter provided is the name of the javascript test.

I also of course had to add the factorial function in the Math.js. This code looks like this:


function factorial(n) {
if (n > 1) {
return n * factorial(n - 1);
}
else {
return 1;
}
}

This factorial function uses recursion to return the factorial of a number. The code is almost the same as a C# based function for the factorial.

Then I just ran the unit test with Ctrl+R and Ctrl+T and saw it pass in the test results. Great stuff Steven Walther! I believe this is the correct way to do unit tests in javascript, i.e. not using QUnit.

The next obvious task is to implement more code to Steven Walther's JavascriptUnitTestLibrary.js file. This should be a near future task I will look into.

I have looked at other parts of unit testing MVC applications. Unit testing controllers are actually very good supported, as these are ordinary classes, which requests can be mocked. The unit testing of views is possible using the RazorSingleFileGenerator or RazorGenerator extension (although many means that unit testing a MVC view should be avoided).

One open issue is how to unit test a MVC 3 Razor helper, I will look into this perhaps using RazorSingleFileGenerator extension in the near future..



Saturday, 6 August 2011

Automatic DisplayAttribute using PostSharp

The Problem


I worked with a MVC 3 web application the other day and was asked to translate the properties to Norwegian. The MVC 3 views are written in Razor view engine and the models are set to DataContract classes. These classes consists of multiple properties and each property needs to have a DisplayAttribute where the Name property is set to the text to display. An overload of the DisplayAttribute is to provide the type of a Resource file (public) followed by the Name attribute, which will in this case be the Resource key inside the Resource file.

After translating large DataContract classes with many DataMember properties, I thought this was a very tedious process. Another challenge was that I got runtime
exceptions when opening the MVC 3 view in a browser just to see an exception being
thrown at me because the resource file did not have a matching resource key which
should be tied to a property by given Name in the DisplayAttribute.

Attributes being difficult


The source of this problem is actually that Attributes in C# cannot define the Resource key directly, but by a string literals. The reason for this is limitations in the types supported in the parameters of a attribute. The ResourceType of the DisplayAttribute is set to the Resource file Type (the resx file is actually a class, inspect the designer.cs file to see its structure). The Name attribute is as previously mentioned a string literal, hardly very refactoring friendly.

Finding a solution


In another project at my work we have used PostSharp to aid in such repetitive tasks, where each property or class needs to be tagged with attributes in a certain pattern. I created a test project and implemented a PostSharp attribute / aspect called AutoDisplayAttribute. This attribute is set on the class level and will decorate all properties with a required display attribute and a resource key set to the property name. The client of this aspect can enforce lookup in the Resource File which means an error will be raised if there are no matching Resource key. The default behavior of this aspect is to avoid setting the DisplayAttribute if no matches are found in the Resource File specified (forceLookup).


Download ILSpy and SharpCrafter's PostSharp


I also used ILSpy to inspect the results in the DLL file of my test project, and the properties were all decorated with my desired DisplayAttribute. ILSpy is free software and is similar to Reflector. The tool is very useful to inspect metadata for DLL files and disassemble them to reveal the source code.

ILSpy

If you have not used PostSharp earlier, you need to download the setup from SharpCrafters. The version I used is PostSharp version 2.1 CTP 3. The download page should be available here:

PostSharp 2.1 Community Edition CTP 3

The PostSharp.dll file must be added in the References to your test project to test out the source code I will present next.

The source code for the AutoDisplayAttribute



The source code for the AutoDisplayAttribute follows below.



// We set up multicast inheritance so the aspect is automatically added to children types.
[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
[Serializable]
public sealed class AutoDisplayAttribute : TypeLevelAspect, IAspectProvider
{

private Type _resourceType;
private bool _forceLookUp;

public AutoDisplayAttribute(Type resourceType, bool forceLookup = false) : base()
{
_resourceType = resourceType;
_forceLookUp = forceLookup;
}

// This method is called at build time and should just provide other aspects.
public IEnumerable ProvideAspects(object targetElement)
{
Type targetType = (Type)targetElement;
var targetTypeProperties = GetTargetTypeProperties(targetType).Distinct();

// Add a Display attribute to every relevant property.
foreach (PropertyInfo property in targetTypeProperties)
{
if (!property.IsDefined(typeof(NotAutoDisplayAttribute), false) &&
!property.IsDefined(typeof(DisplayAttribute), false))
{
if ((!_forceLookUp) && (_resourceType.GetProperty(property.Name) == null))
{
continue;
}
CustomAttributeIntroductionAspect introduceDisplayAspect =
CreateDisplayAttributeIntroductionAspect();
InitDisplayAttributeForProperty(introduceDisplayAspect, property);
yield return new AspectInstance(property, introduceDisplayAspect);
}
}
}

private void InitDisplayAttributeForProperty(CustomAttributeIntroductionAspect introduceDisplayAspect, PropertyInfo property)
{
introduceDisplayAspect.CustomAttribute.NamedArguments.Add("ResourceType", _resourceType);
introduceDisplayAspect.CustomAttribute.NamedArguments.Add("Name", property.Name);
}

private static PropertyInfo[] GetTargetTypeProperties(Type targetType)
{
return targetType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
}

private static CustomAttributeIntroductionAspect CreateDisplayAttributeIntroductionAspect()
{
CustomAttributeIntroductionAspect introduceDisplayAspect =
new CustomAttributeIntroductionAspect(
new ObjectConstruction(typeof(DisplayAttribute).GetConstructor(Type.EmptyTypes)));
return introduceDisplayAspect;
}
}

[AttributeUsage(AttributeTargets.Property)]
public sealed class NotAutoDisplayAttribute : Attribute
{

}



AutoDisplayAttribute code explained


The class above generates the DisplayAttribute for properties inside the
class the AutoDisplayAttribute is applied on, which is the Attribute which is used to lookup the string to display for a given property.


The TypeLevelAspect is the parent class for AutoDisplayAttribute and the class also
implements the IAspectProvider interface. The interface consists of the public method ProvideAspects which will return an IEnumerable of AspectInstance. All these supportive classes and interface is part of the PostSharp API which is used in the code to provide the "magic" post-compilation code executed right during/after the default compilation process.

Talk and embrace


I like this AutoDisplayAttribute a lot. The aspect will definately be a time saver. If you set forceLookup to true on all classes that should have translated properties (usually data contracts), excluding the properties tagged with NotAutoDisplayAttribute, you will get compilation errors when the Resource lookup defined in a Display(Name="MyProperty", ResourceType=typeof(MyResourceType)], which is a huge benefit compared to having run time exceptions thrown at you when the display lookup fails. To fix such an exception, add the resource key and associated resource value in the resource file and build again. If the build went fine, the display attributes are set up. When you refactor a property (i.e. rename), the AutoDisplayAttribute will indirectly require that the resource key is also refactored. To avoid this, it is possible to rather stick to adding the DisplayAttribute manually, but try to keep up this when having DataContract classes with many properties that must be translated and displayed using a resource file. Instead, when having AutoDisplayAttribute on all data contracts and forcing lookup, the compilation errors will guide you to keep the lookup process in a "type-safe" manner, requiring that for each property name there must be a resource key with the same case-sensitive name. In addition, this attribute / aspect is a huge time saver and when the data contracts are tagged with this attribute, it merely consists of adding the [AutoDisplay(typeof(MyResource), forceLookup:true)] tag at the class (instead of lots of [Display(..)] attributes polluting your data contract..

Use-case of this attribute


A minimalistic example follows.

Consider this data contract class. Note the AutoDisplayAttribute at the top of the class.


[AutoDisplay(typeof(Resource1), forceLookup:true)]
public class TestModel
{

public DateTime? BirthDate { get; set; }

public string FirstName { get; set; }

}


Lets follow up with a simple razor view sample



@Html.LabelFor(model => model.BirthDate)
@Html.TextBoxFor(model => model.BirthDate, new { id = "dtpBirthDate" })

@Html.LabelFor(model => model.FirstName)
@Html.TextBoxFor(model => model.FirstName, new { id = "tbFirstName" })


Of course, this attribute is very general and can be used in other frameworks
than MVC 3. When running the application, the labels should now use the value from the Resource file by given resource key.

Please note that the forceLookup is set default to false. To enforce lookup and letting the compiler aiding you that the resource file do indeed have the resource key, set the forceLookup to true explicitly.

In the end, a screen shot from ILSpy to show the magic revealed.



Download sample solution here:

Download sample MVC 3 solution with AutoDisplayAttribute implementation


Regards, Tore Aurstad

Sunday, 17 July 2011

Slides about Ecmascript 5 arrays

I am publishing some slides about Ecmascript 5 arrays written in Norwegian in this article.