Testowanie kompatybilnosci przegladarek dla Helpers w MonoRail

Jul 31, 2008 - 3 minute read -

Helpers w MonoRail są często wykorzystywane do generowania kodu Html. Bywają sytuacje kiedy tworzony Html powinien wyglądać inaczej dla różnych przeglądarek. Czasem do wykrycia rodzaju oraz wersji przeglądarki stosuje się System.Web.HttpRequest.Browser, który zwraca klasę System.Web.HttpBrowserCapabilities. Niestety to rozwiązanie ma trzy zasadnicze wady:

  • Trudno jest mockować klasę HttpBrowserCapabilities
  • Rozwiązanie to opiera się na pliku browscap.ini. W momencie uruchamiania aplikacji  z serwera firmy hostingowej, nie mamy żadnej kontroli nad aktualizacja pliku browscap.ini.
  • System.Web.HttpRequest różni się od  Castle.MonoRail.Framework.IRequest przede wszystkim tym, że IRequest nie ma property Browser :) i nie korzysta z HttpBrowserCapabilities :). Całe szczęście.

Pozostaje nam stare dobre rozwiązanie a mianowicie własnoręczne rozpoznawanie “HTTP_USER_AGENT” w naszym Helperze.

public virtual bool IsCompatibleBrowser()
{
    string agent = Context.Request.Params["HTTP_USER_AGENT"];
 
    // IE
    if (agent.IndexOf("MSIE") >= 0 && agent.IndexOf("Windows") >= 0 && agent.IndexOf("Opera") < 0)
    {
        var match = Regex.Match(agent, @"(?<=MSIE )[\d\.]+");
        return (match.Success && float.Parse(match.Value, CultureInfo.InvariantCulture) >= 5.5);
    }
...

Lecz w jaki sposób to testować ? Najprostszym sposobem jest wykorzystanie istniejących we frameworku MonoRail klas typu stub.

using Castle.MonoRail.Framework.Test;
...
// SUT = System Under Test czyli mój helper
private MyHelper _sut;
 
[SetUp]
public void SetUp()
{
    _sut = new MyHelper();
 
    _sut.SetController(new HomeController(), new ControllerContext());
    _sut.SetContext(new StubEngineContext(new StubRequest(), new StubResponse(), new UrlInfo("area", "home", "index", "/app", "sdm")));
    _sut.ServerUtility = new StubServerUtility();
}

Przydadzą nam się linki do dwóch stron, które zawierają zbiór wszelakiej maści “HTTP_USER_AGENT”.

Dzięki nim łatwo możemy stworzyć następujące testy

// IE 5.5+ on Windows
[TestCase(@"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; Media Center PC 5.0; .NET CLR 1.1.4322)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; Dealio Deskball 3.0)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; NeosBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)")]
// FireFox 1.5+
[TestCase(@"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1")]
[TestCase(@"Mozilla/5.0 (X11; U; Linux x86_64; sv-SE; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12")]
[TestCase(@"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.4) Gecko/20060614 Fedora/1.5.0.4-1.2.fc5 Firefox/1.5.0.4 pango-text")]
[TestCase(@"Mozilla/5.0 (X11; U; Darwin Power Macintosh; en-US; rv:1.8.0.12) Gecko/20070803 Firefox/1.5.0.12 Fink Community Edition")]
[TestCase(@"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8) Gecko/20051201 Firefox/1.5")]
public void IsCompatibleBrowser_ThisBrowserShouldBeCompatible(string agent)
{
    _sut.Context.Request.Params["HTTP_USER_AGENT"] = agent;
    Assert.That(_sut.IsCompatibleBrowser());
}
 
// IE < 5.5 on Windows
[TestCase(@"Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT; .NET CLR 1.0.3705)")]
// IE on Mac
[TestCase(@"Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)")]
[TestCase(@"Mozilla/4.0 (compatible; MSIE 5.5b1; Mac_PowerPC)")]
[TestCase(@"Mozilla/5.0 (MSIE 7.0; Macintosh; U; SunOS; X11; gu; SV1; InfoPath.2; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)")]
// FireFox < 1.5
[TestCase(@"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b4) Gecko/20050908 Firefox/1.4")]
[TestCase(@"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.13) Gecko/20060410 Firefox/1.0.8")]
[TestCase(@"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2b) Gecko/20020923 Phoenix/0.1")]
public void IsCompatibleBrowser_ThisBrowserShouldNOTBeCompatible(string agent)
{
    _sut.Context.Request.Params["HTTP_USER_AGENT"] = agent;
    Assert.That(!_sut.IsCompatibleBrowser());
}

Nadmienię tylko, że korzystam z wersji NUnit 2.5 Alpha-3 Release, stąd atrybut “TestCase”, który jest odpowiednikiem np. “RowTest” w MbUnit.