Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

MVC na ASP.NET – Testování jednotek

16.15 - 1. prosince 2007 | Webdesign

Již delší dobu jsem chtěl napsat článek o tom, proč je MonoRail lepší, když chceme, aby se projekt dal testovat. Jenže vždycky nějak nebyl čas. Navíc se blíží vypuštění ASP.NET MVC, takže nakonec z toho bude trošku obecnější pojednání než jsem původně plánoval.

WebForms testování

Než si ukážeme jak snadné je testovat MVC, nejprve si povíme, že i WebForms se dají testovat. Ano, ale vyžaduje to větší kázeň a víc práce. :) Většinou stejně použijete MVP pattern nebo jeho blízké příbuzné. Pokud tedy nechcete psát testy, které simulují livecycle stránky a dekódují ViewState. (Ano, dotahuju to ad absurdum, ale i tak to může vypadat.)

Aby se tedy kód dal snadno testovat, měl by se co nejvíce oddělit od stránky.

Klasickým modelem tedy je využití MVP vzoru, kdy aspx stránka obsahuje pouze logiku pro prezentaci dat a implementuje rozhranní View, přes které komunikuje s Presenterem. Díky tomu, že Presenter obsahuje téměř veškerou logiku, je ideálním místem pro zacílení našich testů. Pro účely testů pak implementujeme stub nebo mock rozhranní view. Na něm pak sledujeme jak ho Presenter ovlivňuje.

Předchozí diagram ukazuj, že Presenter zná rozhranní View. Stránka, která toto rozhranní implementuje, se však musí postarat o to, aby byl presenter ve správnou chvíli zavolán. Možný scénář zachycuje ukázka kódu.

public class BlogViewPage : System.Web.UI.Page, IBlogView {
  BlogPresenter presenter;

  protected void Page_Init(object sender, EventArgs e) {
    presenter = new BlogPresenter(this); // injekce View
  }

  protected void Page_Load(object sender, EventArgs e) {
    presenter.LoadArticles();
  }

  // implementace IBlogView ...
}

Na to, že to stránka udělá správně, se už musíme spolehnout. Otestovat i takto jednoduchý kód, je už trošku náročnější práce…

MVC testování

MVC frameworky jako MonoRail nebo ASP.NET MVC, přicházejí s podobným schématem by default. V podstatě nás přímo nutí psát web tak, aby se dal lépe testovat. :) Nebudu přehánět, když řeknu, že ASP.NET MVC byl psán se zřetelí na velice snadné testování a obsahuje i sadu mock objektů (např. pro HttpContext). MonoRail dokonce přináší i Fixtures a Asserty pro snadnější testování – bohužel jsou psané pouze pro NUnit, který nepoužívám.

Tento diagram se od předchozího mírně liší. Controller např. netuší jaké má View rozhranní, proto s ním nikterak nepracuje. Prostě zavolá RenderView(*název*, *objekt s daty*) a spoléhá se na ViewFactory že všechno zařídí. Navíc stránka do poslední chvíle netuší, jestli něco bude dělat. Tady totiž proces zpracování začíná u routingu, který vybere správný controller, viz předchozí díl.

Dostáváme se i k lepšímu objektovému návrhu, kde každá třída je zodpovědná za provedení pouze jednoho úkolu (stránka v MVP těch úkolů řeší hned několik). To se opět lépe testuje. Máme sadu několika komponent s jednoduchými závislostmi a každá má na starosti pouze jednu část z procesu.

Pro dnešek to tady ukrouhnu. Bude-li nějaké příště, ukážeme si nějaké praktické ukázky. Možná :)

Související

Castle RC3 a Microsoft MVC

07.48 - 9. října 2007 | Webdesign

Vůbec jsem si toho nevšiml, ale RC3 verze Castle je již několik týdnů venku. Stáhnout si jí můžete ze SourceForge.

Další zajímavou zprávou je. že Microsoft pracuje na vlastním ASP.NET MVC frameworku, který bude umožňovat plnou testovatelnost, IoC kontejnery, ASPX jako view bez ViewState a Page lifecyklu a spoustu zajímavých vychytávek využívajících generika a nové možnosti C#3. První CTP by se měla objevit do konce roku a releas někdy na jaře roku příštího. Release by měl být podobný jako AJAX Extensions, časem se pak zařadí přímo do .net frameworku.

Zajímavý je pohled vývojářů MonoRailu. Vítají zdravou konkurenci a podle všeho se budou snažit využít všech výhod ASP.NET MVC a MonoRail budovat dále nad ním.

Související

MonoRail – Instalace

13.27 - 3. září 2007 | ASP.NET 2.0

Na jednu zásadní věc jsem v prvním díle zapomněl – tedy spíš jsem s ní počítal, ale nakonec jsem jí nedal prostor – a tou je instalace.

Existují, přinejmenším, tři možné způsoby získání MonoRailu, potažmo celého projektu Castle. Buďto si stáhnete instalátor (aktuálně verze RC2 RC3, která vyšla někdy koncem minulého roku koncem září), nebo využijete služeb build serveru a stáhnete si poslední stabilní build vývojové verze. Třetí možností je získat aktuální zdrojové kódy ze Subversion a celý projekt sestavit s NAntem.

Instalátor je klasický balíček MSI, který za vás udělá špinavou práci:

  • Nahraje všechny potřebné soubory na disk,
  • Zaregistruje potřebné knihovny do GAC,
  • Zaregistruje na lokálním IIS příponu .rails pro ISAPI filtr ASP.NET,
  • Přidá dva nové projekty (MonoRail a ActiveRecord) a průvodce do Visual Studia (2003, 2005 SP1).

Nevýhodou tohoto řešení, je neaktuálnost celého kompletu, na druhou stranu je výhodou, že nám zamete cestičku a můžeme rovnou vyvíjet.

Z build serveru si můžete stáhnout aktuální stabilní verzi knihoven v ZIP balíčku. Je to mužnost oba postupy zkombinovat, ale možná se vyplatí používat prozatím RC2 verzi a počkat si na verzi RC3, která by již brzy měla spatřit světlo světa.

Update

14 dní po vydání toho článku spatřila světlo světa RC3 verze Castle, takže některé výše zmíněné věty ztratili na aktuálnosti. :)

Založení projektu

Předpokládám, že jsme si Castle nainstalovali pomoci MSI balíčku. Máme Visual Studio 2005 ve verzi Standard a vyšší s nainstalovaným WebApplication projektem nebo SP1. Dáme vytvořit nový projekt a zobrazí se nám obrazovka podobná té následující:

Nový projekt

Červeně označené jsou nově přidané projekty

  1. Knihovna s podporou persistence pomocí ActiveRecord
  2. Webová aplikace MonoRail

Pro začátek si vystačíme pouze s MonoRail projektem, protože i ten má podporu pro ActiveRecord a tak můžeme model později přesunout do samostatné knihovny. Takže dáme vytvořit nový MonoRail projekt. Spustí se nám jednoduchý průvodce, který nám přednastaví projekt podle našich potřeb.

V prvním kroku si vybereme, který View Engine chceme používat (samozřejmě jde změnit později v konfiguraci), jestli chceme zapnout integraci s Windsor kontejnerem a jestli zapnout podporu pro routing.

Ve druhém kroku se nás průvodce zeptá, jestli chceme vytvořit také testovací projekt (NUnit s podporou pro testování MonoRail). Samozřejmě chceme :) Průvodce nám vytvoří základní strukturu projektu podobnou následujícímu obrázku.

Struktura projektu

V takovéto kostře si můžete vyzkoušet ukázky z předešlých dílů, snad by měly fungovat…

Jak funguje MonoRail

13.20 - 17. srpna 2007 | ASP.NET 2.0

Po letmém seznámení s frameworkem MonoRail (MR) je tu první část slibovaného seriálu. V dnešním díle se ponoříme do technických principů frameworku.

Základem MR je klasický IHttpHandler známý z ASP.NET, který se stará o zpracování požadavků přicházejících na server. Ve výchozím stavu zpracovává požadavky s příponou .rails, ale protože tato není na většině hostingů nastavena na ISAPI filtr ASP.NET, dá se nastavit zpracování přípony jiné (často ashx), která je webovému serveru známá a je spojená s ASP.NET filtrem.

Handler rozparsuje adresu a snaží se najít vhodný Controller a jeho metodu, která požadavek zpracuje a předá data na patřičný View. Vypadá to asi následovně. Na handler přijde požadavek ve tvaru /home/index.rails, handler se pokusí vyhledat třídu HomeController, která dědí ze třídy Controller, a u ní metodu Index(). Takže controller pro tento požadavek by vypadal asi následovně:

public class HomeControler : Controller {
  public void Index()  {
    PropertyBag["hello"] = "Pozdrav z jednokolejky";
  }
}

Takový controller by se měl nacházet v projektu ve složce controllers. Vlastnost PropertyBag je slovník (asociativní pole), který předává data z controlleru na view. Aby se nám to celé mohlo někde zobrazit, potřebujeme ještě tedy view. Ve složce /views/home/ si vytvoříme soubor index.brail (Brail je jedním z ViewEnginů) do kterého zadáme:

<html>
  <head>
    <title>Pozdrav</title>
  </head>
  <body>
    <h1>${hello}</h1>
  </body>
</html>

Řetězec ${hello} bude na výstupu nahrazen textem z PropertyBagu. Dolar složené závorky totiž prochází lokální proměnné a snaží se z nich získat hodnotu. Pokud taková proměnná neexistuje zavolá se metoda GetParametr, která projde kolekce PropertyBag, Flash, Request apod. a snaží se v nich nalézt klíč, kterým je text mezi závorkami. Hodnota je pak vypsána namísto dolarové funkce. :) Dolarová funkce je takový shortcut pro tento zápis: <?brail output hello ?> což je obdoba <?php echo $hello; ?> v PHP nebo <%= hello %> v ASP.

Celá skládačka do sebe zapadne, když do prohlížeče zadáme adresu http://server/home/index.rails. Díky příponě rails se požadavek předá Handleru MonoRail. Ten rozparsuje adresu a snaží se najít třídu HomeController, kterou jsme vytvořili, takže success. V této třídě hledá metodu Index, tu máme taky, další bod k dobru. Tato metoda nám nastaví v PropertyBagu hello na hodnotu „Pozdrav z jednokolejky“. Dále handler hledá vhodné view, které jsme také vytvořili. Předá mu Context, zpracuje se šablona a nakonec bude do prohlížeče odesláno HTML.

<html>
  <head>
    <title>Pozdrav</title>
  </head>
  <body>
    <h1>Pozdrav z jednokolejky</h1>
  </body>
</html>

Pro dnešek vše.

Související

Začínáme s jednokolejkou

16.10 - 14. srpna 2007 | ASP.NET 2.0

Jedním z fenoménů poslední doby ve webovém vývoji jsou bezesporu Ruby on Rails (RoR). Framework určený k RAD Agile vývoji používající objektový přístup a postavený na návrhových vzorech jako je MVC nebo Active Record. Framework je určený pro jazyk či platformu Ruby, to je jeho výhoda i omezení zároveň. Málokdo se má chuť nebo čas se po nocích učit novým jazykům a stávat se vícenásobným robotem.

RoR není rozhodně jediným projektem s podobnou filosofií. My dotneťáci máme krom WebForms, které se snaží přihnout webový vývoj desktopovým zvyklostem (událostmi řízený, stavový), podobný framework, který je navíc opensource. Tento framework se jmenuje MonoRail a oněm bude následující článek a možná i mini seriálek :)

MonoRail

Z názvu by se mohlo zdát, že má projekt něco společného s Monem, opensource implementací dotnetu, ale není tomu tak, krom toho, že MonoRail běží i na Monu 1.1. MonoRail je součást opensource projeku Castle, který si klade za cíl RAD v Enterprise prostředí. Jeho součástí jsou frameworky ActiveRecord (ORM Persistence layer postavený nad NHibernate), Windsor container (Inversion of Control), DynamicProxy (vytváří Proxy třídy z Interfejsů) a právě MonoRail. Všechny frameworky umějí pracovat samostatně, ale jejich největší síla je v jejich spolupráci.

Co je tedy MonoRail? Je to MVC framework inspirovaný ActionPackem běžící na platformně dotnet. Je to náhrada ASP.NET WebForms, ale ty mohou sloužit jako ViewEngine, nebo běžet v jedné aplikaci s MonoRails vedle sebe. Dalšími ViewEnginy jsou NVelocity (port Velocity pod dotnet) nebo Brail (Views jsou psaná v jazyce Boo, což je skriptovací Python like jazyk pro dotnet). Preferovanější je asi NVelocity, ale vývoj Brailu je živější, a WebForms se pro změnu skoro nepoužívají (kvůli PageLife cyklu, který v MonoRailu neexistuje). MonoRail se vám může oproti ASP.NET zdát oldskůlovější, ale opak je pravdou. MonoRail přináší zjednodušení, vrací se k webovému vývoji (bezestavový, Request/Response), staví na osvědčených metodách a zrychluje celý vývoj. Konec řečí, pojďme na věc :)

Model

Model obecně slouží jako zdroj/zpracovávač dat aplikace. Podle toho, jak je vaše aplikace složitá, je bohatý váš model :). Zpravidla se jedná o Domain Model, Business logiku, nebo cokoli jiného, co má na starosti ověřování obchodních pravidel, persistenci a získávání dat. Pro jednoduchost stačí vygenerovat Entity podle DB schématu pomocí ActiveRecord Generatoru nebo naopak vytvořit model a z něj vygenerovat schema.

[ActiveRecord]
public class User : ActiveRecordBase {
  [PrimaryKey] public int Id { get; set; }
  [Property] public string Name { get; set; }
  ...
}

Pro zjednodušení napsáno v C# 3.0 :) ActiveRecord plně využívá atributů k popisu schematu. Dědění třídy ActiveRecordBase není nutností, pro začátek stačí vědět, že nám přidává k entitě spoustu metod pro databázový přístup. Vhodnější pravděpodobně bude využít interface IRepository<T> z projektu Rhino.Commons, který využívá Repository pattern.

View

View jsou obvykle soubory obsahující kusy HTML kódu a prezentační logiky. K zapouzdření prezentační logiky lze využít tzv. View komponent (obdoba UserControls, ale většinou mnohem obecnější). Existují tu i layouty, což je obdoba MasterPages.

<html>
  <head>
    <title>Layout</title>
  </head>
  <body>
    ${ChildOutput}
    <p class="footer">Společná patička.</p>
  </body>
</html>

Takto vypadá velice zjednodušený layout. ${ChildOutput} bude nahrazen obsahem jednotlivých view.

Controler

Kontroler spojuje svět View se světem Modelu. Řídí činnost view mění stavy Modelu. Je to to, co dělá aplikaci aplikací.

[Scaffolding(typeof(User))]
public class UsersController : Controller {
}

Teď když zadáme něco jako http://localhost:12345/users/new.rails tak dostaneme formulář pro zadávání nových uživatelů. (V případě, že doimplementujeme třídu User, aby měla všechny potřebné vlastnosti).

Pro dnešek bych tedy ukončil první představovací článek a v příštích spotech bychom se mohli podívat na tuto zajímavou technologii trošku blíž…