Search This Blog

Monday 27 June 2011

Screw Unit – Teamcity Integration

I had to setup up client side tests to run for my team on Teamcity. I initially thought I should use rake to do this, but then I had to leverage the fact that my team is comfortable with the .Net stack and not so much with Ruby. At this point I just thought i should use a unit test to run my screw unit test via Watin in a browser. This idea is available in a lot of other blogs for QUnit tests. The unit test opens the suite.html , parses the file and reports if the test failed or passed.This works fine. But then when a test failed I had to either look at the logs of the build or had to navigate to the Url, this feedback was ok but not great

I tried to write a teamcity test runner for screw unit which will send messages to TeamCity , but this was hard work and the effort involved was simply too much

If not real time feedback from a test runner, at least seeing the suite.html as a tab on my build would be good.. so I just pushed the artifacts for the build to include the Screw Unit test pack and set up a new tab in TeamCity server config file (main.config file) called Screw Unit Report. This tab would open the html file for the tests from the artifacts. So now I have TeamCity showing the Screw Unit suite as a tab, that's better, the only thing is when you click on the tab it runs the tests every time, but that's not such a big deal really Smile. The effort involved in setting this up was 30 minutes. (I already knew how to setup tabs in TeamCity )

So to summarize

1. Write a unit test runner which will use Watin to open the Screw Unit test suite.html file.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Diagnostics;
   4: using System.IO;
   5: using System.Linq;
   6: using System.Threading;
   7: using MbUnit.Framework;
   8: using NHamcrest.Core;
   9: using WatiN.Core;
  10:  
  11: namespace Tests
  12: {
  13:     [TestFixture]
  14:     [Timeout(600)]
  15:     public class TestRunner
  16:     {
  17:         private FireFox browser;
  18:  
  19:         [SetUp]
  20:         public void SetupBrowser()
  21:         {
  22:             browser = new FireFox();
  23:         }
  24:         /// <summary>
  25:         /// Tests that ScrewUnit tests pass
  26:         /// </summary>
  27:         [Test]
  28:         [Category("ScrewUnitTests")]
  29:         public void RunAllTestsFromSuite()
  30:         {
  31:             var screwUnitTestFile = Path.Combine(Environment.CurrentDirectory, @"Javascript\ScrewUnit\tests\spec\suite.html");
  32:             browser.GoTo(@"file:///" + screwUnitTestFile);
  33:             browser.WaitForComplete(5000);
  34:  
  35:             var resultsDiv = browser.ElementWithTag("h3", Find.ByClass("status"));
  36:             resultsDiv.WaitUntil(() => resultsDiv.Exists && !resultsDiv.Text.ToLower().Contains("Running"), 30000);
  37:  
  38:             AssertThatTestsHavePassed(resultsDiv);
  39:         }
  40:  
  41:         private static void AssertThatTestsHavePassed(Element resultsDiv)
  42:         {
  43:             var resultsArray = resultsDiv.Text.Split(new[] { ' ' });
  44:  
  45:             var numberOfFailures = Int32.Parse(resultsArray.ElementAt(2));
  46:  
  47:             Assert.That(numberOfFailures, Is.EqualTo(0), string.Format("{0}. Click on the Screw Unit Report Tab to see the details", resultsDiv.Text));
  48:         }
  49:  
  50:         [TearDown]
  51:         public void TearDownTestRunner()
  52:         {
  53:             browser.Dispose();
  54:             Thread.Sleep(2000);
  55:             var browserProcesses = Process.GetProcesses()
  56:                     .Where(process => process.ProcessName.ToLower().Contains("firefox") && process.StartInfo.UserName.ToLower().Contains("build"));
  57:                     browserProcesses.Each(p => p.Kill());
  58:         }
  59:        
  60:  
  61:     }
  62:     public static class Extensions
  63:     {
  64:         public static void Each<T>(this IEnumerable<T> collection, Action<T> action)
  65:         {
  66:             foreach (var item in collection)
  67:             {
  68:                 action(item);
  69:             }
  70:         }
  71:       
  72:         public static void WaitUntil(this Element element, Func<bool> predicate, int timeout)
  73:         {
  74:             var startTime = DateTime.Now;
  75:  
  76:             while (!predicate())
  77:             {
  78:                 Thread.Sleep(1000);
  79:                 var now = DateTime.Now;
  80:  
  81:                 if ((now - startTime).TotalMilliseconds > timeout) throw new TimeoutException("Timed out waiting for condition to become true");
  82:             }
  83:         }
  84:     }
  85: }

2. Push the Screw Unit test suite into the artifacts of your build in the team city configuration of your build

3. Configure the main.config file located at <TeamCity Install Folder>\.BuildServer\configuration\confg to create a new tab.

Run your build and you should be able to see the screwunit report on the build server now

   1: <server>
   2:  
   3: <report-tab title="Screw Unit Report" basePath="ScrewUnit.zip" startPage="tests/spec/suite.html" />
   4:  
   5: </server>
   6:  

screwunittests-report

You could use the screwunit test sample i took from git hub to test this Screw Unit Tests sample

No comments: