Daniel Kolman

Jak ladit unit testy s ReSharperem

| 0 comments |

Tak jsem si nedávno do svého VS2005 nainstaloval nový zpomalovač ReSharper 2.0.1. Vypadá to moc chytře (někdy až moc - např. intellisense má VS lepší a daleko rychlejší), a v nové verzi je integrované spouštění unit testů. Když otevřete nějakou třídu s testama, vedle metod se objeví zelenožluté puntíky, kterými se dá jednoduše spustit nebo debuggovat unit test. Spouštění zafungovalo samo a bez problémů, jenže ladění ne a ne se rozběhnout. Pořád to místo unit test metody spouštělo celý projekt.

Pokud máte podobný problém, zkuste ho vyřešit takhle:

1. Pokud jste někdy laborovali s TestDriven.Net, zkontrolujte nastavení projektu. Otevřete Properties projektu obsahující test. Přejděte na záložku Debug. Ve skupině "Start Action" musí být vybráno "Start project" (někdy tam může být nastavený TestDriven).

2. V menu "ReSharper – Options…" zobrazte "Unit Testing" (úplně dole) a ve skupině "Debugging Method" vyberte "Use the project being tested". Výchozí hodnota je při instalaci nastavena na "Use the current startup project", což je, dle mého skromného názoru, volovina.

3. Pak už můžete spouštět testy kliknutím na zelenožlutý puntík vlevo od metody s atributem Test.

Také můžete sledovat průběh spouštění testů spolu s podrobným výstupem v okně Unit Test Runner. Pokud nevyskočí samo, otevřete ho z menu "ReSharper - Windows - Unit Test Runner". Takže nepotřebujete NUnit GUI a nemusíte si pořizovat TestDriven.

Jeden háček to ale má. Při každém testování R# změní v nastavení Solution výchozí startup projekt na právě testovaný projekt, takže pokud pak chcete normálně spustit aplikaci, musíte znovu nastavit výchozí projekt.

UPDATE: Pokud máte ReSharper verze 2.5 nebo nižší, nebudete moci debuggovat projekty umístěné v nějaké Solution Folder. Ve verzi 3.0 už to funguje.

Jak rozšířit XPath o vlastní funkce?

| 0 comments |

Že jazyky spojené s XML lze rozšiřovat, ví i můj jedenapůlroční synovec. Přidat si do XSLT šablony vlastní funkce je triviální prkotina a na netu existují tisíce návodů jak to udělat. Buď šoupnete funkci přímo do XSLT šablony do <ms:script> elementu, nebo přidáte objekt implementující kýžené funkce do XsltArgumentList objektu metodou AddExtensionObject (což je hezčí neboť to přímo nabádá k reuse). Takový přehled možností je zde. Jenže s XPath je to o něco komplikovanější.

Pokud voláte XPath dotazy nad nějakým XML dokumentem přímo z kódu, musíte na to jít úplně jinak. Zřejmě to není tak obvyklý scénář, protože jsem šťoural internet skrz naskrz a vůbec nebylo lehké přijít na nějakou stránku s návodem jak to udělat. Trvalo celkem dlouho než jsem objevil tohle: HOW TO: Implement and Use Custom Extension Functions When You Execute XPath Queries in Visual C# .NET.

Klíčový trik spočívá ve vytvoření vlastního XSLT kontextu, tedy třídy dědící od XsltContext. V ní předefinujete dvě metody: ResolveFunction a ResolveVariable. Když XPath parser narazí na něco, co vypadá jako funkce nebo proměnná kterou nezná, zavolá jednu z těchto metod a my máme šanci podstrčit mu vlastní implementaci. Řešení je to ale o něco složitější než u XSLT, protože musíte vrátit objekt implementující správné rozhraní - IXsltContextFunction nebo IXsltContextVariable. Ovšem s návodem už je to brnkačka, takže nemá cenu dál rozebírat detaily:-)

Jak zjistit celkovou velikost ViewState?

| 0 comments |

Když si zapnete podrobné trasování běhu stránky pomocí elementu <trace> v souboru web.config, ASP.NET vám do stránky vypíše strom ovládacích prvků a informaci o velikosti jejich ViewState a ControlState. Jaká je ale celková velikost dat odesílanýchve skrytém HTML poli __VIEWSTATE?

Na internetu lze nalézt několik návodů, jak přidat informaci o velikosti ViewState do trace logu. Jenže všechny co jsem našel zjišťují velikost podle Request["__VIEWSTATE"], ale to je navrácený ViewState, odeslaný z předchozí stránky! Pokud nás zajímá, kolik dat odesíláme ve ViewState aktuálně zpracovávané stránky, musíme použít daleko špinavější trik.

Výchozí PageStatePersister stránky pro ViewState je HiddenFieldPageStatePersister, který v metodě Save() zkomprimuje ViewState a ControlState a vloží jej do interního textového pole ClientState stránky. Stránka jej pak později narenderuje do jednoho nebo více skrytých polí __VIEWSTATE (záleží na nastavení vlastnosti stránky MaxPageStateFieldLength). No a tak si zjistíme jak je toto pole dlouhé a přidáme to do trace logu:

protected override void Render(HtmlTextWriter writer)
{
#if DEBUG
System.Reflection.PropertyInfo secretState =
this.GetType().GetProperty(
"ClientState",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic
);
string viewState = (string)secretState.GetValue(this, null);
if (viewState != null)
Trace.Warn("ViewState Size", viewState.Length.ToString());
else
Trace.Warn("ViewState Size", "0");
#endif
base.Render(writer);
}

No a je to. Informace o velikosti ViewState je vidět přímo v trace logu stránky! Dobrý, ne? Reflexe interního pole je ovšem špinavá technika a jsou k ní potřeba určitá práva. Pro ladění stránek a velikosti ViewState je to však príma.