<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>AspectWorks &#187; Testování</title>
	<atom:link href="http://www.aspectworks.com/category/testing/feed" rel="self" type="application/rss+xml" />
	<link>http://www.aspectworks.com</link>
	<description>Vyvíjíme chytré webové aplikace pro střední a velké podniky</description>
	<lastBuildDate>Thu, 26 Jan 2012 14:25:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>XPath a Selenium testy</title>
		<link>http://www.aspectworks.com/2012/01/xpath-a-selenium-testy</link>
		<comments>http://www.aspectworks.com/2012/01/xpath-a-selenium-testy#comments</comments>
		<pubDate>Thu, 05 Jan 2012 09:02:32 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[ @cs]]></category>
		<category><![CDATA[Testování]]></category>
		<category><![CDATA[xpath]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3083</guid>
		<description><![CDATA[XPath je dotazovací jazyk (query language) pro XML dokument. Nečekejte náhradu w3schools tutorialu, ale dozvíte se jak najít element v DOMu pomocí funkcí a atributů. Na názorném příkladu si ukážeme,<a href="http://www.aspectworks.com/2012/01/xpath-a-selenium-testy" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>XPath je dotazovací jazyk (query language) pro XML dokument. Nečekejte náhradu <a href="http://www.w3schools.com/xpath/">w3schools tutorialu</a>, ale dozvíte se jak najít element v <a href="http://cs.wikipedia.org/wiki/Document_Object_Model">DOMu</a> pomocí funkcí a atributů. Na názorném příkladu si ukážeme, jak lze XPath využít při psaní Selenium testů webových aplikací. Selenium používá jako <a href="http://release.seleniumhq.org/selenium-remote-control/0.9.0/doc/java/com/thoughtworks/selenium/Selenium.html">lokátory</a> například id, name, css selektor, text odkazu nebo právě XPath.<br />
<span id="more-3083"></span></p>
<p>Mějme následující HTML stránku.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;User list&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;table&gt;
			&lt;tr&gt;
				&lt;td&gt;Joe Smith&lt;/td&gt;
				&lt;td&gt;&lt;a href=&quot;edit.do?id=1&quot;&gt;Edit&lt;/a&gt; | &lt;a href=&quot;delete.do?id=1&quot;&gt;Delete&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
				&lt;td&gt;Eddie Johnson&lt;/td&gt;
				&lt;td&gt;&lt;a href=&quot;edit.do?id=2&quot;&gt;Edit&lt;/a&gt; | &lt;a href=&quot;delete.do?id=2&quot;&gt;Delete&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
				&lt;td&gt;Jack McCarthy&lt;/td&gt;
				&lt;td&gt;&lt;a href=&quot;edit.do?id=3&quot;&gt;Edit&lt;/a&gt; | &lt;a href=&quot;delete.do?id=3&quot;&gt;Delete&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;
		&lt;button&gt;New user&lt;/button&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>V testovacím scénáři potřebujeme editovat uživatele &#8216;Eddie Johnson&#8217;.</p>
<pre class="brush: plain; title: ; notranslate">/html/body/table/tbody/tr[2]/td[2]/a[1]</pre>
<p>Toto je plný XPath dotaz. Nicméně lokátory je třeba co nejvíce abstrahovat od struktury stránky, aby vám jejich drobná změna nerozbila testy.</p>
<pre class="brush: plain; title: ; notranslate">//a[@href='edit.do?id=2']</pre>
<p>To ovšem přepokládá, že víme jaké má Eddie id.</p>
<pre class="brush: plain; title: ; notranslate">//a[contains(@href,'edit.do')][2]</pre>
<p>Ani tentokrát není dotaz ideální, protože spoléháme na to, že Eddie bude na druhém řádku tabulky.</p>
<pre class="brush: plain; title: ; notranslate">//tr//*[contains(text(), 'Eddie Johnson')]</pre>
<p>Takto nalezneme element obsahující text &#8216;Eddie Johnson&#8217;. Nicméně potřebujeme vybrat odkaz sice na stejné řádku ale v jiném sloupci. Řešením je najít předka pomocí klíčového slova <strong>ancestor</strong>. Nalezení odkazu na daném řádku už je hračka. Výsledný dotaz vypadá následovně.</p>
<pre class="brush: plain; title: ; notranslate">//tr//*[contains(text(), 'Eddie Johnson')]/ancestor::tr/td/a[contains(text(), 'Edit')]</pre>
<p>Příklady si můžete vyzkoušet ve Firefox pluginu <a href="https://addons.mozilla.org/en-US/firefox/addon/xpather/">XPather</a>.<br />
S nainstalovaným pluginem se vám kontextové menu (pravé tlačítko myši) rozšíří o možnost &#8222;Show in XPather&#8220;.</p>
<p><img class="aligncenter size-full wp-image-3088" title="xpath" src="http://www.aspectworks.com/wp-content/uploads/2012/01/xpath.png" alt="Ukázka pluginu XPather" width="755" /></p>
<p><strong>Související články</strong></p>
<p><a href="http://www.aspectworks.com/2010/12/konfigurace-selenium-testu-ve-springu">Konfigurace Selenium testů ve Springu</a><br />
<a href="http://www.aspectworks.com/2010/06/selenium-a-navrhovy-vzor-page-objects">Selenium a návrhový vzor Page Objects</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/01/xpath-a-selenium-testy/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Jak na mock HTTP serveru</title>
		<link>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru</link>
		<comments>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru#comments</comments>
		<pubDate>Mon, 05 Sep 2011 12:35:12 +0000</pubDate>
		<dc:creator>Roman Valina</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=2664</guid>
		<description><![CDATA[Pro jednoho z naších zákazníků dodáváme C2DM &#8211; zasílání notifikací na mobilní telefon s operačním systémem Android. Tato služba je implementována jako HTTP request, ve kterém pošlete zprávu, registrační identifikátor<a href="http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Pro jednoho z naších zákazníků dodáváme <a title="C2DM" href="http://code.google.com/android/c2dm/">C2DM</a> &#8211; zasílání notifikací na mobilní telefon s operačním systémem Android. Tato služba je implementována jako HTTP request, ve kterém pošlete zprávu, registrační identifikátor instance zařízení s androidem a C2DM server se postará o doručení.<span id="more-2664"></span></p>
<p>Narazil jsem ale na problém jak vytvořit unit test který ověří, správný formát odesílané notifikace. Problém je právě v tom, jak namockovat chování C2DM serveru bez toho, abych musel někde rozebíhat Jetty či nedejbože Tomcat.</p>
<p>Testovaný kód vypadá nějak takto:</p>
<pre class="brush: java; title: ; notranslate">
private static int sendMessage(String message, URL url) throws IOException {
   // create connection
   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setRequestMethod(&quot;POST&quot;);
    // post data
   DataOutputStream output = new DataOutputStream(connection.getOutputStream());
    output.writeBytes(&quot;message=&quot;message);
    output.flush();
    output.close();
    // establish connection
   connection.connect();
    // return errocode
   return connection.getResponseCode();
}
</pre>
<p>Umím vytvořit mock interfacu (viz. EasyMock , PowerMock ect.), dokonce i stub konkrétní třídy. Final třídu <a title="URL" href="http://download.oracle.com/javase/6/docs/api/java/net/URL.html">URL</a> zkrátka nepodědíte a testovanému kódu pak &#8222;nepředhodíte&#8220;.</p>
<p>Narazil jsem na knihovnu <a title="simple" href="http://www.simpleframework.org/">simple</a>, která velice jednoduše na několika řádcích na pár sekund rozběhne „webový server“. Vy pak můžete snadno nasimulovat chování protějšího serveru.</p>
<p>Vytvoříte třídu implementující interface org.simpleframework.http.core.Container</p>
<pre class="brush: java; title: ; notranslate">
public class MockC2dmServer implements Container {
  protected String capturedMessage;
  public void handle(Request request, Response response) {
     try {
       capturedMessage = request.getParameter(&quot;message&quot;);
     } catch (IOException e1) {
       capturedMessage = null;
     }
    if(capturedMessage != null) {
      response.setCode(HttpURLConnection.HTTP_OK);
    } else {
      response.setCode(HttpURLConnection.HTTP_BADREQUEST);
    }
  }
}
</pre>
<p>Samotné vytvoření serveru a test pak může vypadat nějak takto:</p>
<pre class="brush: java; title: ; notranslate">
@Test
public void basicSenderTest() throws Exception {
  MockC2dmServer mockServer = new MockC2dmServer();
   // binds server to socket on adress
  Connection connectionServer = new SocketConnection(mockServer);
  SocketAddress address = new InetSocketAddress(&quot;localhost&quot;,8080));
  connectionServer.connect(address);
   // test method
  String message = &quot;message text&quot;
  C2dmNotificationSender.sendNotification(message, new URL(&quot;http://localhost:8080&quot;);
  Assert.assertEquals(message, mockServer.capturedMessage);
}
</pre>
<p>Uznávám, že tento způsob testování má svá rizika, například vám nikdo nezaručí, že port 8080 bude volný, to však jde minimalizovat například metodou, která vám nějaký volný port najde, ale to už není tématem tohoto článku. Pokud někdo z vás přijde na jiné, lepší řešení rád si ho přečtu v diskuzi pod článkem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Proč psát javovské testy v Groovy II</title>
		<link>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii</link>
		<comments>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii#comments</comments>
		<pubDate>Tue, 22 Mar 2011 10:28:18 +0000</pubDate>
		<dc:creator>Tomáš Piňos</dc:creator>
				<category><![CDATA[Homepage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=982</guid>
		<description><![CDATA[Druhá část blogu o psaní javovských testů v Groovy přinese méně slov a více kódu. Témata: Deklarace testovacích metod s JUnit Implementace rozhranní “mapou” Capture Libovolné řetězce jako názvy metod<a href="http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<div>
<p>Druhá část blogu o <a href="http://www.aspectworks.com/cs/blog/2011/02/proc-psat-javovske-testy-v-groovy-i/">psaní javovských testů v Groovy</a> přinese méně slov a více kódu.<br />
<span id="more-2560"></span><br />
Témata:</p>
<ul>
<li><a href="#deklarace">Deklarace testovacích metod s JUnit</a></li>
<li><a href="#rozhranni">Implementace rozhranní “mapou”</a></li>
<li><a href="#capture">Capture</a></li>
<li><a href="#nazvy_metod">Libovolné řetězce jako názvy metod</a></li>
<li><a href="#shouldFail">shouldFail?</a></li>
<li><a href="#test_xml">Testování XML výstupů</a></li>
<li><a href="#dalsi">A další&#8230;</a></li>
<li><a href="#maven">Konfigurace Mavenu</a></li>
</ul>
<p>Zkusili jste už psát testy v Groovy? K čemu dalšímu Groovy používáte? Podělte se o své zkušenosti v diskuzi pod článkem.</p>
<h3><a name="deklarace">Deklarace testovacích metod s JUnit</a></h3>
<p>Testovací metody můžeme označit @Test anotací tak, jak to zavedla JUnit 4. Druhou možností je psát testovací třídy jako potomky <a href="http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html">GroovyTestCase</a> a testovací metody začínat prefixem “test”.</p>
<pre class="brush: groovy; title: ; notranslate">
class Test1 {
  @Test
  void &quot;notification message handling&quot;() {
    Assert.fail()
  }
}
class Test2 extends GroovyTestCase {
  void test1() {
    fail(&quot;notification message not handled&quot;)
  }
}
</pre>
<p>GroovyTestCase dědí z třídy junit.framework.TestCase a přidává pár šikovných drobností navíc (<a href="#shouldFail">shouldFail</a>).</p>
<h3><a name="rozhranni">Implementace rozhranní “mapou”</a></h3>
<p>V Groovy můžeme rozhranní implementovat pomocí <a href="http://groovy.codehaus.org/Groovy+way+to+implement+interfaces">closures a map</a>. Pomocí closure:</p>
<pre class="brush: groovy; title: ; notranslate">
def accountDao = { new Account(number: “AX001”, balance: 999G) } as AccountDao
</pre>
<p>Tato closure implementuje všechny metody AccountDao pomocí jednoho kódu (akademický, ale někdy užitečný příklad). Pokud bych chtěl brát v úvahu parametry metod, mohu je v closure deklarovat jako pole &#8211; Object[] params.</p>
<p>Implementace pomocí mapy:</p>
<pre class="brush: groovy; title: ; notranslate">
def accountDao = [ get: { new Account(number: “AX001”, balance: 999G) } ] as AccountDao
</pre>
<p>Mapa implementuje jen metodu get. Rozhranní takto můžeme implementovat i jen částečně &#8211; volání neimplementovaných metod skončí NPE. Je to výborná zkratka pro implementaci různých testovacích stubů (nebo mocků, chcete-li).</p>
<h3><a name="capture">Capture</a></h3>
<p>Implementace rozhranní za pomoci map nebo closures může výrazně zjednodušit situace, kde bychom jinak v Javě museli použít např. EasyMock a jeho metodu <a href="http://easymock.org/api/easymock/2.4/org/easymock/Capture.html">capture</a>. Jako příklad uvedu zjednodušený test z našeho blogu o <a href="http://www.aspectworks.com/cs/blog/2011/02/test-metody-tvorici-objekty/">testech metod tvořících objekty</a>.</p>
<pre class="brush: groovy; title: ; notranslate">
class UserServiceTest {
  @Test
  public void createUser() {
    def userService = new UserServiceImpl()
    userService.userDao = { User user -&gt; assert &quot;tomas&quot; == user.username } as UserDao
    userService.createUser(&quot;tomas&quot;)
  }
}
</pre>
<p>Test ověří, že metoda UserService.createUser správně vytvoří instanci třídy User. Zkuste výsledný kód porovnat s implementací pomocí EasyMocku a capture (převzato z <a href="http://www.aspectworks.com/cs/blog/2011/02/test-metody-tvorici-objekty/">citovaného blogu</a>).</p>
<pre class="brush: java; title: ; notranslate">
public class UserServiceTest {
  private UserServiceImpl userService;
  private UserDao userDao;
  @Before
  public void setUp() {
    userService = new UserServiceImpl();
    userDao = createMock(UserDao.class);
    userService.setUserDao(userDao);
  }
  @Test
  public void createUser() {
    Capture&lt;User&gt; capturedUser = new Capture&lt;User&gt;();
    userDao.save(capture(capturedUser));
    replay(userDao);
    userService.createUser(&quot;pavel&quot;);
    User user = capturedUser.getValue();
    assertEquals(&quot;pavel&quot;, user.getUsername());
    verify(userDao);
  }
}
</pre>
<p>Java dobrý, Groovy lepší?</p>
<h3><a name="nazvy_metod">Libovolné řetězce jako názvy metod</a></h3>
<p>Pěknou možností je nazývat metody libovolnými řetězci.</p>
<pre class="brush: groovy; title: ; notranslate">
@Test void &quot;notification message handling&quot;() {
  // ...
}
</pre>
<p>Maven potom zobrazí výsledek běhu testu následujícím způsobem.</p>
<pre>Failed tests:
  notification message handling(test.NotificationTest)</pre>
<p></p>
<h3><a name="shouldFail">shouldFail?</a></h3>
<p>Metody <a href="http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html#shouldFail(groovy.lang.Closure)">shouldFail</a> třídy GroovyTestCase slouží pro přehledné řešení situací s výjimkami a elegantně obchází obvyklou konstrukci s try &#8211; catch blokem.</p>
<pre class="brush: groovy; title: ; notranslate">
shouldFail(NullPointerException) {
  new Hashtable()[&quot;key&quot;] = null
}
shouldFail(IllegalArgumentException) {
  new HashMap(-1)
}
</pre>
<p>A co jsem myslel obvyklou konstrukcí s try &#8211; catch blokem?</p>
<pre class="brush: java; title: ; notranslate">
    try {
      Hashtable ht = new Hashtable();
      ht.put(&quot;key&quot;, null);
      fail();
    } catch (NullPointerException e) {
      // ok
    }
    try {
      new HashMap(-1);
      fail();
    } catch (IllegalArgumentException e) {
      // ok
    }
</pre>
<p>První příklad testuje vložení null hodnoty pod určitým klíčem do Hashtable &#8211; očekáváme, že pokus skončí výjimkou NPE (jinak fail). Podobně v druhém příkladu by vytvoření HashMap velikosti -1 mělo skončit výjimkou IAE.</p>
<h3><a name="test_xml">Testování XML výstupů</a></h3>
<p>Častým předmětem testů je ověření, jestli nějaký XML výstup odpovídá očekávanému tvaru. Groovy nabízí pro parsing XML mimojiné třídu <a href="http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlSlurper">XmlSlurper</a>. Její použití znamená, že nepíšete XPath výrazy, neiterujete přes DOM, ale přistupujete k obsahu XML stále prostředky Groovy jazyka.</p>
<p>Příklad z dokumentace:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;records&gt;
    &lt;car name='HSV Maloo' make='Holden' year='2006'&gt;
        &lt;country&gt;Australia&lt;/country&gt;
        &lt;record type='speed'&gt;Production Pickup Truck with speed of 271kph&lt;/record&gt;
    &lt;/car&gt;
    &lt;car name='P50' make='Peel' year='1962'&gt;
        &lt;country&gt;Isle of Man&lt;/country&gt;
        &lt;record type='size'&gt;Smallest Street-Legal Car at 99cm wide and 59 kg in weight&lt;/record&gt;
    &lt;/car&gt;
&lt;/records&gt;
</pre>
<p>Použití třídy XmlSlurper:</p>
<pre class="brush: groovy; title: ; notranslate">
def records = new XmlSlurper().parseText(...)
assert 2 == records.car.size()
def firstRecord = records.car[0]
assert 'car' == firstRecord.name()
assert 'Holden' == firstRecord.@make.text()
assert 'Australia' == firstRecord.country.text()
</pre>
<p>Co se čte lépe &#8211; //car[1][@name='HSV Maloo'] nebo car[0].@name.text() == “HSV Maloo”?</p>
<h3><a name="dalsi">A další&#8230;</a></h3>
<p>Mezi další killer vlastnosti Groovy patří vytváření nových instancí, <a href="http://groovy.codehaus.org/Builders">buildery</a> pro vytváření stromových struktur objektů nebo podpora pro práci s <a href="http://groovy.codehaus.org/Collections">kolekcemi</a>. Pěkně akční český přehled lze nalézt třeba v článku <a href="http://java.cz/article/8020">Groovy je žůžo</a>.</p>
<p>Groovy má v arzenálu i podporu pro vytváření mock objektů. <a href="http://docs.codehaus.org/display/GROOVY/Groovy+Mocks">Standardní přístup</a> mě jako uživatele EasyMocku nepřesvědčil, ale <a href="http://gmock.org/">GMock </a>stojí za to. A nezapomínejme na <a href="#rozhranni">mapy</a>, ty vyřeší mnoho potřeb.</p>
<p>I když toho Groovy nabízí hodně a ještě víc, rozhodnout se psát testy v Groovy neznamená opustit skvělou testovací infrastrukturu z Javy. Knihovny jako EasyMock, PowerMock, Hamcrest, … a libovolné jiné můžete stejným způsobem používat dál.</p>
<h3><a name="maven">Konfigurace Mavenu</a></h3>
<p>Podporu Groovy začleníme do projektu jednoduše jako závislost na Groovy artefaktu.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;org.codehaus.groovy&lt;/groupId&gt;
    &lt;artifactId&gt;groovy&lt;/artifactId&gt;
    &lt;version&gt;1.7.5&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Pro správný běh testů je ještě třeba nakonfigurovat build plugin pro kompilaci testů v Groovy.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
    &lt;groupId&gt;org.codehaus.gmaven&lt;/groupId&gt;
    &lt;artifactId&gt;gmaven-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.3&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;testCompile&lt;/id&gt;
            &lt;goals&gt;&lt;goal&gt;testCompile&lt;/goal&gt;&lt;/goals&gt;
            &lt;configuration&gt;
                &lt;sources&gt;
                    &lt;fileset&gt;
                        &lt;directory&gt;${pom.basedir}/src/test/java&lt;/directory&gt;
                        &lt;includes&gt;&lt;include&gt;**/*.groovy&lt;/include&gt;&lt;/includes&gt;
                    &lt;/fileset&gt;
                &lt;/sources&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>Příklad popisuje možnost, kdy jsou .groovy zdrojáky ve stejném adresáři jako testy v Javě. Pokud bychom testy umístili do adresáře src/test/groovy, nebylo by třeba v konfiguraci zahrnovat uvedený fileset.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Proč psát javovské testy v Groovy I</title>
		<link>http://www.aspectworks.com/2011/02/proc-psat-javovske-testy-v-groovy-i</link>
		<comments>http://www.aspectworks.com/2011/02/proc-psat-javovske-testy-v-groovy-i#comments</comments>
		<pubDate>Tue, 22 Feb 2011 08:17:58 +0000</pubDate>
		<dc:creator>Tomáš Piňos</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=959</guid>
		<description><![CDATA[Chcete začít programovat v Groovy? Máte načtenou dokumentaci a tutoriály, ale stále čekáte, až se objeví příležitost, kde Groovy použít? Chtěli byste Groovy použít na aktuálním projektu, ale kvůli různým<a href="http://www.aspectworks.com/2011/02/proc-psat-javovske-testy-v-groovy-i" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Chcete začít programovat v Groovy? Máte načtenou dokumentaci a tutoriály, ale stále čekáte, až se objeví příležitost, kde Groovy použít? Chtěli byste Groovy použít na aktuálním projektu, ale kvůli různým omezením to nejde? Začněte Groovy používat už teď pro psaní testů produkčního Java kódu.<span id="more-959"></span></p>
<p><strong>Proč se možností Groovy testů vůbec zabývat?</strong><br />
Pokud ještě Groovy neznáte, asi váháte, co by vás k jeho použití mohlo vést. Tady je pár “killer” vlastností, které mi psaní testů ulehčují.</p>
<p>Vytváření nových instancí: </p>
<pre class="brush: groovy; title: ; notranslate">def person = new Person(firstname: “Jan”, surname: “Novak”, age: 32)</pre>
<p>&#8230;Zavolá default konstruktor třídy Person a potom settery pro vyjmenované vlastnosti. Příprava testovacích dat je s Groovy velmi jednoduchá.</p>
<p>Implementace rozhranní “mapou”: </p>
<pre class="brush: groovy; title: ; notranslate">def accountDao = [ get: { new Account(number: “AX001”, balance: 999G) } ] as AccountDao</pre>
<p>&#8230;Implementace rozhranní AccountDao &#8211; metoda get vrátí uvedenou instanci, volání ostatních metod skončí NPE. Tohle je výborná zkratka pro implementaci různých testovacích stubů (nebo mocků, chcete-li).</p>
<p>Práce s kolekcemi a closures: </p>
<pre class="brush: groovy; title: ; notranslate">def numbers = accounts.findAll { it.balance &gt; 10000G }.collect { it.number }</pre>
<p>&#8230;Vybere z kolekce účty se zůstatkem &gt; 10.000 a zjistí jejich čísla. S Groovy se i docela složité operace nad kolekcemi dají zapsat jako one-liner. Přehlednosti testů to hodně přidá.</p>
<p>Groovy je plnohodnotný, obecně použitelný jazyk a umí toho samozřejmě mnohem víc. Možnostem Groovy při psaní testů se bude podrobněji věnovat druhý díl článku. V dnešním blogu se snažím ukázat, <em>že</em> není problém začít Groovy používat. V příštím pokračování více popíšu, <em>jak</em> může Groovy výrazně ulehčit některé rutinní činnosti při psaní testů.</p>
<p><strong>Co využití Groovy mění?</strong></p>
<blockquote><p>“To je sice hezké, že Groovy mi může psaní testů zjednodušit, ale co naše infrastruktura? Jak to do sebe zapadá? Buildíme Mavenem, Cobertura nám měří pokrytí kódu testy a používáme Sonar pro sledování různých metrik a kvality Java kódu.”</p></blockquote>
<p>Spouštění Groovy testů Mavenem není problém &#8211; je k dispozici build plugin <a href="http://docs.codehaus.org/display/GMAVEN/Home">gmaven-plugin</a>. Plugin je navěšený na Maven goal testCompile &#8211; takže jeho použitím říkáme Mavenu pouze to, aby Groovy testy zkompiloval. Dál už se spouští Java.</p>
<p>Groovy zdrojáky se totiž kompilují do .class souborů a zjednodušeně tedy platí, že Groovy třídy jsou po kompilaci Java třídami. Problémem není ani použití Cobertury, z pohledu pokrytí kódu se nic nemění.</p>
<p>I po začlenění Groovy do projektu můžeme dál bedlivě sledovat kvalitu kódu. K dispozici je např. <a href="http://docs.codehaus.org/display/SONAR/Groovy+Plugin">Groovy plugin</a> pro Sonar.</p>
<blockquote><p>“A to budu muset kódovat v Notepadu?”</p></blockquote>
<p>Pluginy pro práci s Groovy jsou k dispozici pro prostředí <a href="http://www.jetbrains.com/idea/features/groovy_grails.html">Intellij Idea</a>, <a href="http://groovy.codehaus.org/Eclipse+Plugin">Eclipse</a> i pro <a href="http://groovy.codehaus.org/NetBeans+Plugin">NetBeans</a>. S podporou v Intellij Idea mám dobrou zkušenost a můžu ji doporučit. Pěkně funguje editor (code completion, formátování kódu a pod.), debugger i refactoring.</p>
<p>Jak dobře si vaše ide s Groovy kódem poradí, závisí do značné míry na stylu kódování. Groovy je sice dynamicky typovaný jazyk, to ale neznamená, že dynamické typování musíte vždy a všude využívat. Zjednodušeně platí, že ide může mít potíže tam, kde není upřesnění datový typ. Specifikovat typy u public metod, vlastností nebo parametrů closures nejde proti duchu programování v Groovy. Kód zůstává čitelnější a ide má šanci se v něm vyznat.</p>
<p><strong>Přínos psaní testů v Groovy</strong><br />
Začít používat nový jazyk pro celý projekt je typicky hazard, pokud s ním nemáte dost zkušeností. Začít v Groovy psát testy je konzervativní <em>první krok</em>. Je to výborná příležitost vyzkoušet si produktivitu vývoje v Groovy, podporu jazyka ve svém IDE a také svoji schopnost Groovy zvládat. Protože mocný nástroj v nezkušených rukách nemusí být vždy přínosem. Přitom nemusíte nic slevit ze svých požadavků na pokrytí kódu testy ani na kvalitu kódu v testech samotných.</p>
<p><strong>Shrnutí</strong><br />
Článků o tom, proč a jak psát testy v Groovy je už na webu dost. Mou ambicí proto nebyla originalita, ale snaha šířit dobrý nápad i mezi místní komunitu. Věřím, že psát testy v Groovy je dobrý nápad, který nepřináší pro zavedené projekty větší riziko.</p>
<p>Neříkám “Naučte se Groovy a pište v něm testy”, ale “Umíte trochu Groovy a chcete ho hned začít používat? Začněte v něm psát testy.”</p>
<p>A co vy, máte už s Groovy nebo jiným dynamicky typovaným jazykem zkušenost? Použili jste Groovy na komerčním projektu? Psali byste v něm testy pro Java kód? Podělte se o své zkušenosti v diskuzi pod článkem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/02/proc-psat-javovske-testy-v-groovy-i/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Konfigurace Selenium testů ve Springu</title>
		<link>http://www.aspectworks.com/2010/12/konfigurace-selenium-testu-ve-springu</link>
		<comments>http://www.aspectworks.com/2010/12/konfigurace-selenium-testu-ve-springu#comments</comments>
		<pubDate>Wed, 01 Dec 2010 10:20:00 +0000</pubDate>
		<dc:creator>Pavel Müller</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=858</guid>
		<description><![CDATA[obr.: Greg Robson V minulém článku &#8222;Selenium a návrhový vzor Page Objects&#8220; jsem popisoval, jak strukturovat Selenium testy. Už tam ale nebylo rozebráno, jak je možné, že to celé dohromady<a href="http://www.aspectworks.com/2010/12/konfigurace-selenium-testu-ve-springu" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<div class="imageRight"><a href="http://www.aspectworks.com/wp-content/uploads/2010/12/selenium1.jpg" rel="lightbox[858]"><img class="alignright size-thumbnail wp-image-887" title="selenium" src="http://www.aspectworks.com/wp-content/uploads/2010/12/selenium1-200x161.jpg" alt="" width="140" height="100" /></a><br />
<a rel="cc:attributionURL" href="http://commons.wikimedia.org/wiki/File:Electron_shell_034_selenium.png" rel="lightbox[858]">obr.: Greg Robson</a></div>
<p>V minulém článku &#8222;<a href="http://www.aspectworks.com/2010/06/selenium-a-navrhovy-vzor-page-objects/">Selenium a návrhový vzor Page Objects</a>&#8220; jsem popisoval, jak strukturovat Selenium testy. Už tam ale nebylo rozebráno, jak je možné, že to celé dohromady funguje. Pokusím se tedy ukázat konfiguraci Selenium komponent ve Springu 3.0 a jak si připravit pohodlné předky pro testy a stránky.<span id="more-858"></span><br />
Na unit testy používáme JUnit 4 a k jejich konfiguraci balíček Spring Test. Ten mimo jiné umožňuje vytvořit z test třídy Spring bean a následně jí konfigurovat třeba pomocí <em>@Autowired</em> anotace. Unit test při svém spuštění nastartuje aplikační kontext a v něm vytvoří všechny beany. Tedy ideální prostředek udělat instanci Selenium browseru a nechat si ji injectovat do test casu.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean class=&quot;org.springframework.beans.factory.config.PropertyPlaceholderConfigurer&quot;&gt;
    &lt;property name=&quot;location&quot;
        value=&quot;classpath:selenium-${selenium.configuration:localhost}.properties&quot; /&gt;
    &lt;property name=&quot;systemPropertiesModeName&quot;
        value=&quot;SYSTEM_PROPERTIES_MODE_OVERRIDE&quot; /&gt;
&lt;/bean&gt;
&lt;bean id=&quot;selenium&quot; class=&quot;com.thoughtworks.selenium.DefaultSelenium&quot;
        init-method=&quot;start&quot; destroy-method=&quot;stop&quot;&gt;
    &lt;constructor-arg index=&quot;0&quot; value=&quot;${selenium.host}&quot; /&gt;
    &lt;constructor-arg index=&quot;1&quot; value=&quot;${selenium.port}&quot; /&gt;
    &lt;constructor-arg index=&quot;2&quot; value=&quot;${selenium.browser}&quot; /&gt;
    &lt;constructor-arg index=&quot;3&quot; value=&quot;${webapp.url}&quot; /&gt;
&lt;/bean&gt;
</pre>
<p>Je vidět, že Selenium browser je nakonfigurován pomocí údajů z property souborů. Příjemnou vlastností je, že můžete pomocí systémové property <em>selenium.configuration</em> konfigurovat, jaký property soubor použít. To se hodí hlavně pro střídání prostředí. Jiné nastavení používá vývojář testů a jiné nastavení používá server na kontinuální integraci.</p>
<p>Nyní bych měl ukázat, jak vypadá třída unit testu. Ale samotný test case není jediná komponenta potřebující nakonfigurovaný objekt Selenium. Máme tu ještě stránky podle Page Objects vzoru a další pomocné komponenty. Takže proto je tu abstraktní třída <em>AbstractSeleniumComponent</em>.  Vypadá nějak takto (jako vždy redakčně kráceno):</p>
<pre class="brush: java; title: ; notranslate">
public abstract class AbstractSeleniumComponent {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    protected Selenium selenium;
    @Value(&quot;${webapp.context}&quot;)
    protected String context = &quot;&quot;;
    @Value(&quot;${selenium.timeout:30000}&quot;)
    protected String timeout;
    @Autowired
    protected ApplicationContext applicationContext;
    /**
     * Open URL in web application context and wait for page to load.
     * @param url URL to open. Context relative.
     */
    protected void openAndWait(String url) {
        SeleniumUtils.openAndWait(selenium, context, url, timeout);
    }
}
</pre>
<p>Třída je jednoduchá a očekává, že budou Springem injectovány závislosti. Využívá se novinky ve Springu 3.0, anotace <em>@Value</em> k vyhodnocení property. Třída taky obsahuje řadu pomocných metod usnadňujících život jako je <em>openAndWait()</em>.</p>
<p>Předek pro všechny testy je jednoduchý. Pouze konfiguruje Spring aplikační kontext a implementuje uložení screenshotu prohlížeče v případě neúspěšného testu. Více o této technice <a href="http://www.aspectworks.com/cs/blog/2010/04/junit-anotace-afterfailure/">psal Luboš</a>.</p>
<pre class="brush: java; title: ; notranslate">
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class })
@RunWith(SeleniumRunner.class)
@ContextConfiguration(locations = { &quot;applicationContext.xml&quot; })
public abstract class AbstractSeleniumTest extends AbstractSeleniumComponent {
    @Value(&quot;${selenium.screenshot.dir:/tmp/}&quot;)
    protected String screenshotDir;
    /**
     * Capture a screen shot if test fails.
     * @param failure failure cause
     */
    @AfterFailure
    public void captureScreenShotOnFailure(Throwable failure) {
        // build filename ...
        selenium.captureScreenshot(screenShotPath);
    }
}
</pre>
<p>Ještě potřebujeme i nějakého předka pro jednotlivé stránky. I stránky musí mít přístup k Selenium objektu a musí být schopné &#8222;navigovat&#8220; mezi sebou. Navíc by bylo dobré,  aby takové stránky šly iniciovat a udržovaly konverzační stav. I stránka v browseru může být v nějakém stavu a tak i naše objekty by tomu měly odpovídat. V terminologii Springu je tedy stránka odlišná od jiných Selenium komponent, protože není singleton ale prototype. V kódu se to ale samozřejmě neprojeví.</p>
<pre class="brush: java; title: ; notranslate">
public abstract class AbstractPage extends AbstractSeleniumComponent {
    public &lt;T extends AbstractPage&gt; T navigateTo(Class&lt;T&gt; pageClass, Object... params){
        T page = applicationContext.getBean(pageClass);
        // initialize page
        page.init(params);
        return page;
    }
    protected void init(Object... params) {
    }
}
</pre>
<p>Metoda <em>navigateTo()</em> zajišťuje přechody mezi stránkami. Vyžádá si novou beanu od Springu (prototype) a inicializuje ji.</p>
<p>Testy se stanou Spring beanama automaticky ale naše stránky a další Selenium komponenty je třeba nějak zařadit do aplikačního kontextu. To nejlépe provedeme tak, že najdeme všechny třídy, které jsou nějak anotované, a uděláme z nich beany. Použijeme pak klasický <em>context:component-scan</em>. Pro značkování tříd máme anotaci <em>@SeleniumComponent </em>obsahující i parametr pro definování scopu Spring beany. Můžete tak určit, jestli to má být singleton nebo prototype. Anotace <em>@Page</em> už je pak jen zkratkou k <em>@SeleniumComponent(&#8222;prototype&#8220;)</em>. Navíc se hodí pro případné aspekty. Všimněte si, jak lze v novém Springu anotovat anotace.</p>
<pre class="brush: java; title: ; notranslate">
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SeleniumComponent {
    public String value() default BeanDefinition.SCOPE_SINGLETON;
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@SeleniumComponent(&quot;prototype&quot;)
public @interface Page {
}
</pre>
<p>Teď už jen říct Springu, ať hledá všechny třídy s anotací @SeleniumComponent a ať použije scope definovaný v těchto anotacích. To není zas až takový problém:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;context:component-scan base-package=&quot;com.aspectworks&quot; use-default-filters=&quot;false&quot;
        scope-resolver=&quot;com.aspectworks.awf.selenium.SeleniumComponentScopeResolver&quot;&gt;
    &lt;context:include-filter type=&quot;annotation&quot;
        expression=&quot;com.aspectworks.awf.selenium.SeleniumComponent&quot;/&gt;
&lt;/context:component-scan&gt;
</pre>
<p>Implementace scope resolveru je už jen otázkou správného použití Spring API.</p>
<p>Jak je vidět konfigurace Selenium testů za použití JUnit 4 a Spring Frameworku je elegantní a celkem i jednoduchá. Ukázky kódu jsou pochopitelně zjednodušené, ale pokud bude zájem, není problém je zveřejnit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2010/12/konfigurace-selenium-testu-ve-springu/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JUnit result interceptor</title>
		<link>http://www.aspectworks.com/2010/07/junit-result-interceptor</link>
		<comments>http://www.aspectworks.com/2010/07/junit-result-interceptor#comments</comments>
		<pubDate>Tue, 20 Jul 2010 09:18:40 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Homepage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=648</guid>
		<description><![CDATA[Před nějakou dobou jsme psali o vlastní anotaci @AfterFailure v JUnit testech. Naší motivací byly screenshoty neúspěšných selenium testů. JUnit od verze 4.7 má svoje řešení jménem TestWatchman. TestWatchman je<a href="http://www.aspectworks.com/2010/07/junit-result-interceptor" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Před nějakou dobou jsme psali o vlastní <a href="http://www.aspectworks.com/cs/blog/2010/04/junit-anotace-afterfailure/">anotaci @AfterFailure v JUnit testech</a>. Naší motivací byly screenshoty neúspěšných selenium testů. JUnit od verze 4.7 má svoje řešení jménem <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/rules/TestWatchman.html">TestWatchman</a>.<span id="more-648"></span></p>
<p>TestWatchman je v podstatě interceptor, který můžete zavěsit na události <em>failed, finished, starting a succeeded</em>. Ukažme si na následujícím příkladě, jak zareagovat na neúspěšný test a zjistit jméno třídy a název testu. Tento string používáme jako jméno screenshotu v našich selenium testech. Metoda failed se volá jak při assertationFailed tak při výjimce.</p>
<pre class="brush: java; title: ; notranslate">
import static junit.framework.Assert.fail;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatchman;
import org.junit.runners.model.FrameworkMethod;
public class MyTest {
	@Rule
	public MethodRule watchman = new TestWatchman() {
		@Override
		public void failed(Throwable e, FrameworkMethod method) {
			String methodName = MyTest.this.getClass().getSimpleName() + &quot;.&quot; + method.getName();
			System.out.println(methodName + &quot; has failed!&quot;);
		}
	};
	@Test
	public void testFailed() {
		fail();
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2010/07/junit-result-interceptor/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generátor rodných čísel</title>
		<link>http://www.aspectworks.com/2010/05/generator-rodnych-cisel</link>
		<comments>http://www.aspectworks.com/2010/05/generator-rodnych-cisel#comments</comments>
		<pubDate>Thu, 13 May 2010 08:51:43 +0000</pubDate>
		<dc:creator>Pavel Müller</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=589</guid>
		<description><![CDATA[V poslední době se věnuji automatizovaným Selenium testům jednoho obchodního systému. Při vkládání osob do systému je nutné zadat rodné číslo a systém provádí jeho validaci a sleduje, jestli je<a href="http://www.aspectworks.com/2010/05/generator-rodnych-cisel" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>V poslední době se věnuji automatizovaným Selenium testům jednoho obchodního systému. Při vkládání osob do systému je nutné zadat rodné číslo a systém provádí jeho validaci a sleduje, jestli je v systému unikátní. Abych mohl automatizovat funkčnost zakládání osob, tak jsem se rozhodl, že vytvořím generátor rodných čísel. Není vše ale tak jednoduché, jak by se mohlo zdát.</p>
<p><span id="more-589"></span>Obvykle každý ví, že rodná čísla se tvoří od roku 1954 ve tvaru <em>yymmdd/xxxx</em> a ta starší mají tvar <em>yymmdd/xxx</em>. Pokud je to žena, přičte se k měsíci 50. Také si každý myslí, že by mělo být rodné číslo dělitelné jedenáci. Ale zde je právě kámen úrazu. Vše je trochu jinak.</p>
<p>Poslední desátá číslice přidávaná od roku 1954 je kontrolní a tvoří se tak, že se vydělí devitimístné číslo jedenácti a zbytek po dělení se použije jako desátá kontrolní číslice. Tím je výsledné desetimístné číslo dělitelné jedenácti. Tedy v případě, že zbytek po dělení nebyl 10. V takovém případě je kontrolní číslice rovna 0, ale tím pádem není celé rodné číslo dělitelné jedenácti. Do roku 1985 bylo přiděleno cca 1000 rodných čísel, která nejsou dělitelná 11. Není vyloučeno, že se v minimálním počtu vyskytly i po tomto roce.</p>
<p>Navíc od roku 2004 je zavedena možnost v případě, že jsou v nějaký den vyčerpána všechna platná čtyřčíslí, použít alternativní rodné číslo, u kterého mají muži k číslu měsíce přičteno 20 a ženy 70. A i rodná čísla před rokem 1954 mohou mít čtyřčíslí, pokud se jednalo o dodatečně přidělená rodná čísla (např. při získání občanství).</p>
<p>Více informací třeba na <a title="Wikipedii" href="http://cs.wikipedia.org/wiki/Rodn%C3%A9_%C4%8D%C3%ADslo">Wikipedii</a> nebo na <a href="http://latrine.dgx.cz/jak-overit-platne-ic-a-rodne-cislo">tomto blogu</a>.</p>
<p>Většina aplikací se spokojí s ověřením dělitelnosti jedenácti. Ale to je evidentně špatně. Ještěže nemám tu smůlu a nemám nestandardní rodné číslo :-)</p>
<p>Napsal jsem pro účely Selenium testů generátor rodných čísel s několika možnostmi, jak číslo generovat:</p>
<ul>
<li>pro konkrétní datum a pohlaví</li>
<li>pro věkové rozpětí &#8211; vhodné třeba pro generování mladistvých</li>
<li>oficiální rodné číslo &#8211; dle výše popsaných pravidel</li>
<li>běžné rodné číslo &#8211; takové, které čeká většina aplikací &#8211; dělitelnost 11, standarní tvary</li>
<li>speciální rodné číslo &#8211; takové, které není běžné &#8211; vhodné pro test validace</li>
</ul>
<p>Ukázka použití generátoru:</p>
<pre class="brush: java; title: ; notranslate">
// generates random personal number from 1900 till today
String personalNumber = RcGenerator.generateRc();
// men between 18 and 30
personalNumber = RcGenerator.generateRcForAge(18, 30, Gender.MALE);
// common personal number modulo 11 == 0 which passes most validators
personalNumber = RcGenerator.generateRc(RcType.COMMON);
</pre>
<p>Přiložené třídy můžete volně použít. Budu rád, když najdete chyby nebo generátor vylepšíte, rozšíříte funkčnost a s kódem se zase podělíte.</p>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2010/05/RcGenerator.zip">RcGenerator.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2010/05/generator-rodnych-cisel/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>JUnit anotace @AfterFailure</title>
		<link>http://www.aspectworks.com/2010/04/junit-anotace-afterfailure</link>
		<comments>http://www.aspectworks.com/2010/04/junit-anotace-afterfailure#comments</comments>
		<pubDate>Mon, 26 Apr 2010 11:07:42 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=545</guid>
		<description><![CDATA[Na automatické testování GUI našeho produktu Orinoco používáme framework Selenium. Pro identifikaci a opravu chyby je často klíčové vědět, co uživatel(respektive selenium test) v okamžiku chyby viděl. Selenium umí uložit<a href="http://www.aspectworks.com/2010/04/junit-anotace-afterfailure" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na automatické testování GUI našeho produktu <a href="http://www.orinoco.cz">Orinoco</a> používáme framework <strong>Selenium</strong>. Pro identifikaci a opravu chyby je často klíčové vědět, co uživatel(respektive selenium test) v okamžiku chyby viděl. Selenium umí uložit snímek obrazovky, ale jak definovat okamžik, kdy ho má vytvořit? Nechtěli jsme mít přesně definované, které obrazovky má pokaždé ukládat. Naopak jsme  chtěli snímek jen v případě, když Selenium test selže. A k tomu právě lze využít vlastní anotaci <em>@AfterFailure</em>.<br />
<span id="more-545"></span><br />
Na začátku byla jasná představa: ukládat snímky obrazovky, pokud Selenium test selže. Zbývalo jen   doplnit metodu <i>Selenium#captureScreenshot(String)</i> na správné místo. Narazil jsem na zajímavý článek <a href="https://dev.youdevise.com/YDBlog/index.php?title=capture_screenshots_of_selenium_browser_&amp;more=1&amp;c=1&amp;tb=1&amp;pb=1">Capture Screenshots of Selenium Failures</a>, který popisuje, jak anotaci @AfterFailure a vlastní Runner naprogramovat.</p>
<p>Pozor na pořadí anotací! Řešení popsané ve zmiňovaném článku volá nejprve metodu anotovanou @After a poté teprve @AfterFailure. To samo o sobě není problém, pokud stejně jako my v metodě anotované @After nevoláte metodu <i>Selenium#stop()</i>, která zavírá prohlížeč. To pak vám je získaný snímek obrazovky k ničemu. Rešení je jednoduché, stačí v runneru jen prohodit volání metod v metodě <i>#withAfters(FrameworkMethod, Object, Statement)</i>.
<pre class="brush: java; title: ; notranslate">
@Override
protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
      statement = withAfterFailures(method, target, statement);
      return super.withAfters(method, target, statement);
}
</pre>
<p>Věřím, že vám snímky v případě selhání Selenium testů ušetří čas při opravování bugů.</p>
<p><em>Edit</em><br />
JUnit od verze 4.7 má svoje <a href="http://www.aspectworks.com/cs/blog/2010/07/junit-result-interceptor/">řešení jménem TestWatchman</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2010/04/junit-anotace-afterfailure/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Unit testy nad in-memory databází</title>
		<link>http://www.aspectworks.com/2010/03/unit-testy-nad-in-memory-databazi</link>
		<comments>http://www.aspectworks.com/2010/03/unit-testy-nad-in-memory-databazi#comments</comments>
		<pubDate>Sun, 21 Mar 2010 13:02:31 +0000</pubDate>
		<dc:creator>Richard Šerý</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=496</guid>
		<description><![CDATA[Použití in-memory databází pro testování je poněkud kontroverzní téma, ale nedělejte rychlé soudy &#8211; Tomáš Piňos na svém blogu naznačuje, za jakých okolností má testování za pomoci in-memory databáze svoje<a href="http://www.aspectworks.com/2010/03/unit-testy-nad-in-memory-databazi" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Použití in-memory databází pro testování je poněkud kontroverzní téma, ale nedělejte rychlé soudy &#8211; Tomáš Piňos na svém blogu naznačuje, za jakých okolností má testování za pomoci in-memory databáze svoje opodstatnění. Nenechte si ujít zajímavý článek &#8222;<a href="http://tom2ee-cs.blogspot.com/2010/02/unit-testy-nad-in-memory-databazi.html">Unit testy nad in-memory databází</a>&#8222;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2010/03/unit-testy-nad-in-memory-databazi/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testujeme s rozumem (2.) &#8211; Jak z UC získat TC</title>
		<link>http://www.aspectworks.com/2009/11/testujeme-s-rozumem-2-jak-z-uc-ziskat-tc</link>
		<comments>http://www.aspectworks.com/2009/11/testujeme-s-rozumem-2-jak-z-uc-ziskat-tc#comments</comments>
		<pubDate>Mon, 02 Nov 2009 10:29:42 +0000</pubDate>
		<dc:creator>Zdeněk Jonáš</dc:creator>
				<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=362</guid>
		<description><![CDATA[Při přípravě na testování projektu je zapotřebí vytvořit scénáře (postupy), které budou testeři procházet při testování. Scénáře by v optimálním případě měly pokrývat případy užití, pro které je aplikace vyvíjena.<a href="http://www.aspectworks.com/2009/11/testujeme-s-rozumem-2-jak-z-uc-ziskat-tc" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Při přípravě na testování projektu je zapotřebí vytvořit scénáře (postupy), které budou testeři procházet při testování. Scénáře by v optimálním případě měly pokrývat případy užití, pro které je aplikace vyvíjena. Máme-li rozumně zpracovanou analýzu, může být získání těchto scénářů relativně snadné.<br />
<span id="more-362"></span></p>
<p>Tyto scénáře testů nazýváme „testovanými scénáři“, anglicky test case, zkratkou TC. Co je to TC? Co by měl obsahovat? TC je soubor vstupů, kroků i podmínek a očekávaných výstupů. Ale kde ho vezmeme?</p>
<p>Každá analýza vyvíjeného systému by měla obsahovat případy užití (use cases), dále UC. Tyto scénáře užití lze s výhodou použít pro vytvoření seznamu TC. Jak na to? Ukážeme si na následujícím příkladu.</p>
<div class="example">
<p>Představte si jednoduchý systémový UC na evidenci vydané faktury v nějakém systému. Daný uživatel má právo zadávat faktury pouze do 100 tisíc.</p>
<h4>Basic Flow</h4>
<ul>
<li>1. Uživatel zadá číslo faktury.</li>
<li>2. Systém provede kontrolu čísla faktury.</li>
<li>3. Uživatel vyplní fakturovanou částku.</li>
<li>4. Systém provede kontrolu výše částky.</li>
<li>5. Uživatel vyplní datum splatnosti.</li>
<li>6. Systém provede kontrolu data splatnosti.</li>
<li>7. Systém vytvoří fakturu a podá uživateli zprávu o jejím úspěšném zaevidování.</li>
</ul>
</div>
<p>Nyní máme zpracovaný zcela jednoduchý UC, kde máme základní průchod aplikací. Bohužel svět není jednoduchý a ani náš příklad nemůže být takto jednoduchý. Je zapotřebí se zamyslet a definovat další toky, kterými může tento scénář být přerušen, či pokračovat zcela jinou cestu. Jedná se o tzv. Alternate flows.</p>
<div class="example">
<h4>Alternate flow 1</h4>
<p class="noBottom">Faktura v systému již existuje, nelze přidat.</p>
<ul>
<li>Basic Flow v bodě 2. Systém podá uživateli zprávu o existenci faktury tohoto čísla a UC se tímto ukončí (faktura se nevytvoří).</li>
</ul>
<h4>Alternate flow 2</h4>
<p class="noBottom">Co když částka na faktuře přesáhne hodnotu 100 tis Kč?</p>
<ul>
<li>Basic Flow v bodě 4. Systém podá uživateli zprávu o převýšení maximální hodnoty faktury a UC se tímto ukončí (faktura se nevytvoří).</li>
</ul>
<h4>Alternate flow 3</h4>
<p class="noBottom">Co když zadáme datum splatnosti v minulosti?</p>
<ul>
<li>Basic Flow v bodě 6. Systém podá uživateli zprávu o špatné hodnotě data splatnosti a UC se tímto ukončí (faktura se nevytvoří).</li>
</ul>
</div>
<p>Nyní si sepíšeme do tabulky pod sebe všechny možné scénáře, a pojmenujeme si je. Pojmenování volte rozumně, neboť by se mělo používat skrze celé testování.</p>
<div class="example">
<h3>Sestavení a pojmenování scénářů</h3>
<table border="0">
<tbody>
<tr>
<th>Scénář 1 – založení faktury</th>
<td>Basic Flow</td>
<td></td>
</tr>
<tr>
<th>Scénář 2 – faktura tohoto čísla již v systému existuje</th>
<td>Basic Flow</td>
<td>Alternate flow 1</td>
</tr>
<tr>
<th>Scénář 3 – částka vyšší než 100 tisíc</th>
<td>Basic Flow</td>
<td>Alternate flow 2</td>
</tr>
<tr>
<th>Scénář 4 – datum splatnosti v minulosti</th>
<td>Basic Flow</td>
<td>Alternate flow 3</td>
</tr>
</tbody>
</table>
</div>
<p>Teď již máme identifikovány hlavní scénáře, které budeme potřebovat otestovat. Pro vlastní testování však toto ještě nestačí. Musíme definovat vstupy a očekávané výstupy jednotlivých TC. Vstupy lze identifikovat dle rozhodovacích bloků v UC. Každé alternative flow by mělo být způsobeno nějakou příčinou, vstupem. V našem případě máme situaci poněkud zjednodušenou. V reálných systémech jsou i desítky vstupů. Zde lze s výhodou použít excel, či vhodný TC management nástroj.</p>
<p>V našem případě dochází k startu alternate flow 3 v scénáři č.4: Datum splatnosti v minulosti.<br />
Je tedy evidentní, že v tomto scénáři se rozhodne o provedení alternativního scénáře v bodě 6. Tudíž je zapotřebí zadat číslo faktury, částku a datum splatnosti. Číslo faktury a částka je validní a datum splatnosti je neplatné (Invalid). Další vstupy jsou již pro tento scénář irelevantní a v tabulce se neobjeví.</p>
<p>Nyní vyplňme tabulku. „V“ představuje potřebný validní vstup a „I“ invalidní vstup. Pokud na vstupech nezáleží nebo jsou irelevantní, zanechte příslušné buňku tabulky prázdnou. Názvy jednotlivých TC volíme ve sloupci TC ID# tak, aby odpovídaly testovanému scénáři. V našem případě jde o evidenci faktury, zvolil jsem tedy zkratku IE (Invoice Evidence). V případě velkých systémů nám toto pojmenování pomůže v orientaci.</p>
<div class="example">
<table border="0">
<tbody>
<tr>
<th>TC ID#</th>
<th>Scénář</th>
<th>číslo faktury</th>
<th>částka</th>
<th>datum splatnosti</th>
<th>Očekávaný výsledek</th>
</tr>
<tr>
<td>IE 1</td>
<td>Scénář 1 – založení faktury</td>
<td>V</td>
<td>V</td>
<td>V</td>
<td>Faktura úspěšně založena</td>
</tr>
<tr>
<td>IE 2</td>
<td>Scénář 2 – faktura tohoto čísla již v systému existuje</td>
<td>I</td>
<td></td>
<td></td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
<tr>
<td>IE 3</td>
<td>Scénář 3 – částka vyšší než 100 tisíc</td>
<td>V</td>
<td>I</td>
<td></td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
<tr>
<td>IE 4</td>
<td>Scénář 4 – datum splatnosti v minulosti</td>
<td>V</td>
<td>V</td>
<td>I</td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
</tbody>
</table>
</div>
<p>Nyní máme tabulku validních a nevalidních vstupů. Víme, na kterých vstupech záleží úspěšnost dané operace. Připravíme si testovací prostředí tak, abychom mohli splnit tyto scénáře. Dost často mají UC tzv. preconditions. Tyto precondititons například říkají, že uživatel, který chce založit jiného uživatele, musí mít administrátorská práva. Musíte tedy do systému před začátkem testovaní založit uživatele s administrátorskými právy.<br />
Na základě takto připraveného testovacího prostředí jste již schopni definovat konkrétní tabulku s konkrétními vstupy.<br />
V našem případě vypadá například takto. Pokud používáte excel, doplňte si tabulku o sloupce precondition a postconditions. Tam definujte, co je zapotřebí udělat před spuštěním testu a zároveň co má tester udělat po ukončení testu. (například po sobě v aplikaci uklidit).</p>
<div class="example">
<table border="0">
<tbody>
<tr>
<th>TC ID#</th>
<th>Scénář</th>
<th>číslo faktury</th>
<th>částka</th>
<th>datum splatnosti</th>
<th>Očekávaný výsledek</th>
</tr>
<tr>
<td>IE 1</td>
<td>Scénář 1 – založení faktury</td>
<td>20</td>
<td>45 000</td>
<td>15.1.2010</td>
<td>Faktura úspěšně založena</td>
</tr>
<tr>
<td>IE 2</td>
<td>Scénář 2 – faktura tohoto čísla již v systému existuje</td>
<td>20</td>
<td></td>
<td></td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
<tr>
<td>IE 3</td>
<td>Scénář 3 – částka vyšší než 100 tisíc</td>
<td>21</td>
<td>150 000</td>
<td></td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
<tr>
<td>IE 4</td>
<td>Scénář 4 – datum splatnosti v minulosti</td>
<td>22</td>
<td>23 000</td>
<td>11.9.2001</td>
<td>Faktura nezaložena, uživatel informován.</td>
</tr>
</tbody>
</table>
</div>
<p>Dost často na svých školeních se setkávám s názorem, že tento postup je příliš přebyrokratizovaný a prý zdržuje. Praxe ovšem ukazuje, že problémem není vyplnění tabulky, ale neochota některých (test) analytiků se dopředu zamyslet a definovat tyto scénáře a vstupy. Pokud se ovšem nechcete smířit s intuitivním testováním a postoupit například až k objektivnímu měření kvality, zavedení podobných pravidel vás nejspíše nemine.</p>
<p>Pozorný čtenář teď zareaguje: Vždyť v těch TC nemám přeci kroky, jak mám postupovat? Tehdy ale nehledáme artefakt TC ale Test Script. Čili postup, kterým bude tester postupovat při ověřování konkrétního testovaného případu. Test Scripty psát je časově náročné a mnohdy se musí s měnící aplikací znovu přepisovat. Proč je tedy píšeme?</p>
<p>Rozdíl mezi TC a Test Script je v době jejich vzniku a v tom, kdo tyto artefakty vytváří. Zatímco k definici TC dochází na začátku projektu a provádí je test analytik (dosti často i analytik projektu), tak Test Scripty si píší sami testeři.</p>
<p>Oblast okolo názvů, tvorby TC a organizace práce je natolik rozsáhlá, že by vydala na několik článků. Pokud máme menší projekty a sdílené role, potřebujeme relativně malý aparát. Pokud ovšem projekt přerůstá určitou hranici, je zapotřebí zvolit adekvátní metody přístupu k testování.</p>
<p><a href="http://www.aspectworks.com/cs/blog/2009/08/testujme-s-rozumem-serial/">Předchozí díl: Úvod seriálu</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2009/11/testujeme-s-rozumem-2-jak-z-uc-ziskat-tc/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

