<?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>Blog Macoscope &#187; Cocoa</title>
	<atom:link href="http://blog.macoscope.net/pl/category/cocoa/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.macoscope.net/pl</link>
	<description>prawdziwy software, nie web 2.0</description>
	<lastBuildDate>Wed, 21 Jul 2010 15:27:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Irbis, zwany panterą śnieżną</title>
		<link>http://blog.macoscope.net/pl/2009/08/irbis-zwany-pantera-sniezna/</link>
		<comments>http://blog.macoscope.net/pl/2009/08/irbis-zwany-pantera-sniezna/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 19:01:48 +0000</pubDate>
		<dc:creator>Wojtek Rolecki</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Maktura]]></category>

		<guid isPermaLink="false">http://blog.macoscope.net/pl/?p=725</guid>
		<description><![CDATA[Doczekaliśmy się — w starym dobrym &#8220;under-promise, over-deliver&#8221; stylu, Apple ogłosiło że premiera nowego dużego drapieżnika z gatunku kotowatych odbędzie się nie we wrześniu, jak pierwotnie planowano, ale jeszcze w sierpniu. Co więcej, jak donosi Moje Jabłuszko, Snow Leopard będzie dostępny w Polsce równocześnie ze światową premierą, czyli już 28 sierpnia (to w ten piątek!).
Ale, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.macoscope.net/pl/wp-content/uploads/2009/08/snow_leopard.jpg"><img class="alignleft size-full wp-image-737" title="SL?" src="http://blog.macoscope.net/pl/wp-content/uploads/2009/08/snow_leopard.jpg" alt="SL?" width="300" /></a>Doczekaliśmy się — w starym dobrym &#8220;<em>under-promise, over-deliver</em>&#8221; stylu, Apple ogłosiło że premiera nowego <a href="http://images.google.com/images?hl=en&amp;source=hp&amp;q=snow+leopard">dużego drapieżnika</a> z gatunku kotowatych odbędzie się nie we wrześniu, jak pierwotnie planowano, ale jeszcze w sierpniu. Co więcej, jak <a href="http://mojejabluszko.pl/?p=3529">donosi</a> <a href="http://mojejabluszko.pl/">Moje Jabłuszko</a>, Snow Leopard będzie dostępny w Polsce równocześnie ze światową premierą, czyli już 28 sierpnia (to w ten piątek!).</p>
<p>Ale, przechodząc do rzeczy — jako, że blogiem plotkarskim o orientacji jabłkowo-makowej nie jesteśmy, a poza tym news i tak jest już średniej świeżości — chcieliśmy zakomunikować, że trzymamy rękę na pulsie i Maktura jest aktualizowana na bieżąco, tak aby była zgodna z naszym ulubionym systemem operacyjnym w wersji 10.6.<br />
<span id="more-725"></span><br />
Najbliższa aktualizacja Maktury, która ukaże się naprawdę &#8220;na dniach&#8221;, będzie zawierała już większość wymaganych przez nowy system zmian i poprawek. Niestety nie możemy obiecać, że będzie zawierała wszystkie — testy wciąż trwają, a nie chcemy opóźniać terminu wydania Maktury 1.2. Wszelkie nowo wykryte problemy (odpukać) zostaną usunięte w wersji 1.2.1, którą oczywiście wydamy jak najszybciej.</p>
<p>Jakiego typu problemów może oczekiwać programista przy przejściu na Snow Leoparda? W ogólności zależy to oczywiście od jakości kodu i zgodności z zaleceniami, które Apple publikuje <a href="http://developer.apple.com">tu i ówdzie</a>.</p>
<p>W telegraficznym skrócie, oto rzeczy które spowodowały że zadumaliśmy się na chwilę nad Xcodem:</p>
<ul>
<li>Na samym starcie spotkało nas zaskoczenie — kod, który nie generował żadnych warningów pod Leopardem, w ogóle nie chciał się pod jego śnieżnym wariantem skompilować — dostaliśmy czerwonym komunikatem na dzień dobry. Problemem było zduplikowane w podklasie <em>@synthesize</em> atrybutu zadeklarowanego w klasie wyżej. Głupi błąd, ale kompilator pod 10.5 siedział cicho. :-)</li>
<li>Domyślnie, Xcode pod SL generuje <em>fat-binary</em>, które oprócz kodu dla PPC i x86, zawierają też kod na 64-bitowe procesory Intela (czyli <em>amd64</em> AKA <em>x64</em> AKA <em>x86_64</em>). I co z tego? Niewiele, jeśli byliście czujni, żyliście i kodowaliście w zgodzie z <a title="zaleceniami" href="http://developer.apple.com/documentation/Cocoa/Conceptual/Cocoa64BitGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004247-CH1-SW1" target="_self">zaleceniami</a> Apple (które ukazały się przed wprowadzeniem 10.5 na rynek). Jeśli nie, to spotkać Was może &#8220;klasyczna niespodzianka&#8221;. W szczególności, jeśli lubicie porównywać sobie zmienne zadeklarowane jako <em>int </em>ze stałymi typu <em>NSNotFound</em>, <em>NSIntegerMax</em> itp.</li>
<li>Wygląda na to, że <em>NSArrayController</em> przyjmuje teraz inne domyślne wartości swoich atrybutów, konieczne było zatem przeklikanie się przez IB lub odopowiednie poustawianie ich podczas inicjalizacji.</li>
<li>Kilka losowych problemów z .xibami — usuniętych naszą autorską metodą wypracowaną podczas miesięcy zmagań z Interface Builderem, przy użyciu skomplikowanego systemu kadzideł i mantr szeptanych o poranku.</li>
</ul>
<p>Oprócz powyższych, trzeba oczywiście zwrócić uwagę na kod (klasy i metody), który w 10.4 i 10.5 był oznaczony w dokumentacji Apple jako <em>deprecated</em>. Snow Leopard, jak wiadomo, wprowadza sporo zmian &#8220;pod maską&#8221; systemu, część przestarzałych metod mogła więc zostać usunięta z systemowego API. Podsumowując proces ukompatybilniania Maktury z nowym systemem nie był do tej pory bardzo skomplikowanym zadaniem i oby ten trend się utrzymał :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.macoscope.net/pl/2009/08/irbis-zwany-pantera-sniezna/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testy jednostkowe w Objective-C</title>
		<link>http://blog.macoscope.net/pl/2009/03/testy-jednostkowe-w-objective-c/</link>
		<comments>http://blog.macoscope.net/pl/2009/03/testy-jednostkowe-w-objective-c/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 15:02:56 +0000</pubDate>
		<dc:creator>Zbigniew Sobiecki</dc:creator>
				<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://blog.macoscope.net/pl/?p=359</guid>
		<description><![CDATA[Oprogramowanie można testować na wiele sposobów, w zależności od tego na jakim poziomie chcemy operować, jakie aspekty działania aplikacji chcemy przetestować i do czego wyniki testów mają nam posłużyć. Prawdopodobnie najszerzej praktykowanym sposobem testowania jest tworzenie testów jednostkowych (ang. unit tests). Testy te uruchamiają fragmenty tworzonego kodu i sprawdzają czy efekt ich działania jest zgodny [...]]]></description>
			<content:encoded><![CDATA[<p>Oprogramowanie można testować na wiele sposobów, w zależności od tego na jakim poziomie chcemy operować, jakie aspekty działania aplikacji chcemy przetestować i do czego wyniki testów mają nam posłużyć. Prawdopodobnie najszerzej praktykowanym sposobem testowania jest tworzenie <a href="http://c2.com/cgi/wiki?UnitTest">testów jednostkowych</a> (ang. unit tests). Testy te uruchamiają fragmenty tworzonego kodu i sprawdzają czy efekt ich działania jest zgodny z oczekiwanym.</p>
<p><span id="more-359"></span></p>
<p>Jak łatwo się domyślić, żeby wykorzystać pełne zalety unit testów, w miarę tworzenia nowych funkcjonalności aplikacji powinniśmy dbać o to, aby były one przetestowane, a zatem pisać równolegle kod samych testów. Jeszcze lepiej, kiedy zgodnie z metodologią <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> (Test-Driven Development) testy powstają jako specyfikacja, zanim jeszcze zostanie stworzony kod mogący ją spełniać.</p>
<p>Na pierwszy rzut oka wydawać by się mogło, że pisanie testów to trochę sztuka dla sztuki, zwłaszcza że pochłania dosyć znaczącą ilość czasu podczas rozwoju aplikacji. Jest to niestety często spotykany sposób myślenia. Mniemam, że ma on korzenie w podobnym rozumowaniu jak zasłyszana ostatnio wypowiedź prezesa sporej firmy developerskiej &#8211; &#8220;Czy my naprawdę potrzebujemy tego działu QA? Czy programiści nie mogliby po prostu przestać robić błędy w oprogramowaniu?&#8221;</p>
<p>Dla samych developerów, programowanie testów jednostkowych (zwłaszcza w &#8216;kieracie&#8217; TDD/<a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>) też jest zwykle na początku zadaniem uciążliwym, do którego trzeba ich przekonać. Nie ma w końcu efektu &#8220;instant gratification&#8221; &#8211; rezultatem napisania testu w odróżnieniu od pozostałych części programu nie jest nowa funkcjonalność lub poprawka błędu.</p>
<p>Jednak tworzenie testów jednostkowych bardzo podnosi jakość tworzonego oprogramowania i paradoksalnie, w dłuższej perspektywie wpływa pozytywnie także na szybkość jego rozwoju. Do postawowych korzyści płynących z unit testów można zaliczyć:</p>
<p>    * <strong>Testowanie regresji</strong> &#8211; częste uruchamianie testów w miarę tworzenia nowego kodu aplikacji pozwala łatwo ujawnić popełnione błędy, objawiające się często w najmniej oczekiwanych miejscach, znalezienie których mogłoby być znacznie bardziej problematyczne. Błędy regresyjne bywają szczególnie nieprzyjemne podczas przeprowadzania refaktoryzacji &#8211; tutaj wytworzona<br />
    * <strong>Weryfikacja poprawności projektu</strong> &#8211; często problemy jakie napotykamy przy tworzeniu testów wynikają z konieczności rozebrania struktury naszego kodu na mniejsze części. Nawet w programowaniu obiektowym łatwo o uzyskanie sytuacji, kiedy nie jest to zadanie banalne. Testy uwypuklają taką sytuację na wczesnym etapie i pozwalają zaradzić złemu projektowi w porę, chroniąc nas przed karkołomnymi konstrukcjami w przyszłości.<br />
    * <strong>Dokumentacja</strong> &#8211; nikt nie ma czasu na tworzenie lub/i aktualizowanie dokumentacji. Posługiwanie się językiem innym niż taki, który da się skompilować lub przepuścić przez interpreter zajmuje w procesie tworzenia oprogramowania zwykle poślednie miejsce. Testy przychodzą z pomocą &#8211; często stanowią zestaw przykładów użycia dostępnych klas i fundament na którym możemy zbudować faktyczny kod w innych miejscach. Tutaj szczególnie sprawdza się metodologia <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>.<br />
    * <strong>Kontrola wydajności</strong> &#8211; często narzędzia wspomagające tworzenie i uruchamianie testów jednostkowych umożliwiają mierzenie czasu wykonania pojedynczego testu lub całego ich zestawu, a co za tym idzie &#8211; wydajności samego kodu aplikacji.</p>
<h2>Jak to się robi?</h2>
<p>Testy jednostkowe tworzy się z reguły w oparciu o jeden z dostępnych frameworków służących do tego celu, zwanych kolektywnie <a href="http://en.wikipedia.org/wiki/XUnit">xUnit</a>. Wszystkie są oparte o architekturę stworzoną przez <a href="http://en.wikipedia.org/wiki/Kent_Beck">Kenta Becka</a> i zaimplementowaną pierwotnie w <a href="http://sunit.sourceforge.net/">SUnit</a> &#8211; wersji dla Smalltalka. Większość używanych obecnie języków programowania ma przynajmniej jedną taką bibliotekę &#8211; mamy zatem JUnit dla Javy, JSUnit dla JavaScriptu, oraz PyUnit, HUnit itd. Pełna lista znajduje się tutaj.</p>
<p>Na przykładzie użycia jednego z frameworków dostępnych dla Objective-C przybliżę w dalszej części główne elementy architektury unit testów.</p>
<h2>Narzędzia dostępne dla Objective-C</h2>
<p>Najpopularniejszą biblioteką z serii xUnit dla Objective-C jest <a href="http://www.sente.ch/software/ocunit/">OCUnit</a>, framework stworzony przez szwajcarską firmę Sen:te. Został on wbudowany w Xcode 2.1 i od tego czasu jest dystrybuowany razem z nim. W styczniu 2008 została wydana biblioteka <a href="http://code.google.com/p/google-toolbox-for-mac/">Google Toolbox for Mac</a>, zawierająca wiele wartych uwagi rozszerzeń do OCUnit, umożliwiających między innymi testowanie oprogramowania tworzonego dla iPhone oraz tworzenie testów interfejsu użytkownika. Zautomatyzowane testy UI mogą stanowić nieoszacowaną pomoc w budowaniu aplikacji zawierających interfejs użytkownika, ponieważ są w stanie porównać dowolny jego fragment z plikiem zawierającym wzór, jaki oczekujemy zobaczyć.</p>
<h2>Podstawy OCUnit</h2>
<p>Podobnie jak wiele frameworków z serii xUnit, OCUnit udostępnia klasę bazową, z której należy dziedziczyć przy tworzeniu klas zawierających poszczególne metody testujące. Klasa ta, zwana <i>SenTestCase</i>, zapewnia również mechanizmy przygotowujące środowisko i ewentualne dane do przeprowadzenia testu, jak również czyszczące je po jego wykonaniu.</p>
<p>Załóżmy, że mamy klasę <i>MCDocumentItem</i>, będącą odwzorowaniem pozycji na fakturze i chcielibyśmy przetestować poprawność wyliczania sumy brutto posiadając sumę netto i stawkę podatkową. Pomińmy w tej chwili wszystkie księgowe niuanse i skupmy się na najprostszej ewentualności. Interfejs odpowiedniej klasy <i>MCDocumentItemTest</i> mógłby wyglądać następująco:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;SenTestingKit/SenTestingKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@class</span> MCDocumentItem;
&nbsp;
<span style="color: #a61390;">@interface</span> MCDocumentItemTest <span style="color: #002200;">:</span> SenTestCase <span style="color: #002200;">&#123;</span>
    MCDocumentItem <span style="color: #002200;">*</span>documentItem;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setUp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tearDown;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>testGrossCalculationFromNetAndVatValue;
<span style="color: #a61390;">@end</span></pre></div></div>

<p>Jak widać posiadamy jedną metodę testującą w naszym teście &#8211; <i>testGrossCalculationFromNetAndVatValue</i>. OCUnit działa zgodnie z konwencją, że wszystkie metody zawierający nasz kod testujący będą posiadały nazwę zaczynającą się od &#8220;test&#8221;. Dwie pozostale metody, czyli <i>setUp</i> i <i>tearDown</i> są uruchamiane odpowiednio przed i po każdej z metod testowych. Implementacja naszej klasy mogłaby wyglądać w następujący sposób:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;MCDocumentItem.h&quot;</span>
<span style="color: #6e371a;">#import &quot;MCDocumentItemTest.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> MCDocumentItemTest
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setUp <span style="color: #002200;">&#123;</span>
    documentItem <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>MCDocumentItem new<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>documentItem setName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Suchy chleb dla konia&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>documentItem setUnitName<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;kwintal&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>tearDown <span style="color: #002200;">&#123;</span>
   documentItem <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>testGrossCalculationFromNetAndVatValue <span style="color: #002200;">&#123;</span>
   <span style="color: #002200;">&#91;</span>documentItem setNetPrice<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDecimalNumber</span> decimalNumberWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;100&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#91;</span>documentItem setVatRate<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDecimalNumber</span> decimalNumberWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;0.22&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#91;</span>documentItem setQuantity<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDecimalNumber</span> decimalNumberWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;1&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
   STAssertEqualObjects<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDecimalNumber</span> decimalNumberWithString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;122&quot;</span><span style="color: #002200;">&#93;</span>, <span style="color: #002200;">&#91;</span>documentItem grossValue<span style="color: #002200;">&#93;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;grossValue should be 122, but it was %f instead!&quot;</span>, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>documentItem grossValue<span style="color: #002200;">&#93;</span> floatValue<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></div></div>

<p>Zaimplementowaliśmy zatem wszystkie trzy metody, jakie były nam potrzebne. W <i>setUp</i> tworzymy obiekt documentItem, z którego potem możemy korzystać w metodach testujących. W <i>tearDown</i> &#8220;sprzątamy&#8221; środowisko pozostawione przez nasze testy. Na dobrą sprawę nie musielibyśmy przypisywać pustej wartości do documentItem, ale gdybyśmy nie korzystali z  <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcEssentials.html#//apple_ref/doc/uid/TP40002452-SW1">Garbage Collectora</a>, zapewne chcielibyśmy w tym miejscu zwolnić pamięć zajętą przez stworzone obiekty, lub przywrócić stan aplikacji/danych sprzed testu.</p>
<p>Na początku naszej metody testowej przypisujemy utworzonemu wcześniej przez <i>setUp</i> obiektowi wartości liczbowe, które posłużą nam do przeprowadzenia tego konkretnego testu. Ustalamy zatem cenę netto produktu na 100, wartość podatku  na 0.22 oraz ilość produktu na 1. Oczekiwalibyśmy, że po ustaleniu takich parametrów obiektu klasy <i>MCDocumentItem</i>, wywołanie na nim metody <i>grossValue</i> zwróci wartość brutto równą 122. Sprawdzeniem, czy nasze oczekiwania zostaną spełnione zajmuje się w tym przypadku makro <i>STAssertEqualObjects</i>. Porównuje ono obiekt oczekiwany (zgodnie z obowiązującą konwencją jest pierwszym argumentem) z faktycznym obiektem, zwróconym przez wywołanie metody grossValue. Pozostałe argumenty są opcjonalne. Trzeci argument to wiadomość, jaką chcemy otrzymać kiedy okaże się, że obiekty się od siebie różnią. Jeśli nie podamy tego argumentu, dostaniemy standardowy komunikat informujący nas o różnicach w porównywanych obiektach, jednak czasem chcielibyśmy bardziej zaznaczyć okoliczności zdarzenia lub odpowiednio sformatować podawane informacje &#8211; trzeci i kolejne argumenty służą do tego celu. Stanowią one kolejne argumenty w metodzie stringWithFormat z klasy <i>NSString</i>, pozwalającej odpowiednio zbudować ciąg znaków.</p>
<p>OCUnit dostarcza wiele makr z rodziny STAssert*, takich jak:</p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">STAssertNil
STAssertNotNil
STAssertTrue
STAssertFalse
STAssertEqualObjects
STAssertEquals
STAssertEqualsWithAccuracy
STAssertThrows
STAssertThrowsSpecific
STAssertNoThrow
STAssertNoThrowSpecific
STFail</pre></div></div>

<p>Argumenty dla wymienionych makr budowane są analogicznie do opisanego przykładu &#8211; podajemy oczekiwaną wartość lub wartości wraz z komunikatem błędu.</p>
<h2>Jak to działa w Xcode?</h2>
<p>Aby uruchamiać testy z poziomu naszego projektu w XCode należy dodać nowy target. Na szczęście XCode dostarczany jest z OCUnitem, a bodajże od wersji 3.0 ustawianie testów nie wymaga już takiej ilości dodatkowego voodoo jak ongiś. Obecnie wystarczy właściwie dodać nowy target typu Unit Test Bundle i w zakładce General dodać do &#8220;Direct dependencies&#8221; istniejący target naszej aplikacji.</p>
<p>Uruchomienie testów polega na zmianie aktywnego targetu, następnie klasyczne &#8220;Build &#038; Go&#8221;. Same komunikaty błędów sygnalizowane są wtedy inline w kodzie – jako standardowe ostrzeżenia kompilacji ze wskazaniem linii, w której znajduje się newralgiczna asercja:</p>
<div id="attachment_133" class="wp-caption aligncenter" style="width: 587px"><img class="size-full wp-image-133" title="Błędy testów w XCode" src="http://blog.macoscope.net/pl/wp-content/uploads/2009/03/bledy-testow-w-xcode.png" alt="Błędy testów w XCode" width="577" height="108" /><p class="wp-caption-text">Błędy testów w XCode</p></div>
<p>Testy można uruchamiać także z poziomu linii poleceń, co otwiera drogę do automatyzacji tego procesu i zastosowania w praktyce <a href="http://en.wikipedia.org/wiki/Continuous_Integration">Continous Integration</a>.</p>
<p>Debugowanie samych testów to inna bajka – jeśli chcielibyśmy z jakiegoś powodu wstrzelić się naszym ulubionym debuggerem do kodu naszych testów (nie do testowanego kodu, tylko do kodu który go testuje :-), to niestety potrzebna jest odrobina magii, która polega na dodaniu nowej pozycji w projekcie, tym razem w sekcji Executables. Nowy executable to po prostu otrzymana w wyniku zwykłej kompilacji binarka naszego projektu z dodatkowym parametrem (informującym OCUnit o uruchomieniu wszystkich testów) i dodatkowymi zmiennymi środowiskowymi, które odczyniają pożądane voodoo. Po konkrety odsyłam do <a href="http://chanson.livejournal.com/120740.html">postu</a> Chrisa Hansona.</p>
<h2>Rozszerzenia w GTM</h2>
<p><a href="http://code.google.com/p/google-toolbox-for-mac/">Google Toolbox for Mac</a> wprowadza do OCUnit wiele przydatnych rozszerzeń. Pojawiły się nowe makra STAssert*, zbudowano prosty serwer HTTP do testowania aplikacji pobierających dane za pomocą tego protokołu, dostosowano bibliotekę testującą do iPhone i umożliwiono testowanie bindings.</p>
<p>Najciekawszym, moim zdaniem, rozszerzeniem jest wsparcie dla testowania interfejsu użytkownika. Wsparcie to dzieli się na dwa zestawy funkcjonalności. Pierwszy umożliwia porównywanie wewnętrznego stanu kontrolek z oczekiwanym, a drugi działa analogicznie do fragmentów UI zapisanych w plikach graficznych. Automatyczne testy UI nie są rzeczą trywialną, jednak GTM wydaje sie rozwiązywać je w bardzo przystępny sposób. Jeśli porównanie widoku (i jego subviews) wygenerowanego przez nasz kod z oczekiwanym zawiedzie, utworzy wtedy na pulpicie developera plik zawierający różnice pomiędzy wersjami a także obraz otrzymany w teście. Analogicznie dla porównywania stanu widoków i kontrolek, GTM zachowa się operując na plikach w <a href="http://en.wikipedia.org/wiki/Property_list">formacie .plist</a>.</p>
<p>Co bardzo ważne, GTM zawiera także wsparcie dla ustawiania przed testami UI spójnego środowiska, które pozwoli nam uniknąć niezgodności pomiędzy zmienionymi przez użytkownika ustawieniami systemu. Musimy jednak pamiętać, że jeśli test ma przechodzić na różnych wersjach systemu i rodzajach sprzętu musimy tworzyć oddzielne wersje obrazów testowych z uwagi na różnice jakich nie da się w takim przypadku uniknąć.</p>
<h2>Podsumowanie</h2>
<p>Objective-C nie ma zbyt wielu zaawansowanych narzędzi do testowania. W porównaniu do <a href="http://www.ruby-lang.org">Ruby&#8217;ego</a>, gdzie za pomocą <a href="http://rspec.info/">RSpec</a> możemy pisać testy (czy też, z uwagi na nomenklaturę BDD, specyfikacje) niemalże w języku angielskim, sprawdzać pokrycie kodu przy użyciu <a href="http://eigenclass.org/hiki.rb?rcov">rcova</a>, automatyzując to wszystko za pomocą <a href="http://cruisecontrolrb.thoughtworks.com/">CruiseControl.rb</a>, czy <a href="http://www.zenspider.com/ZSS/Products/ZenTest/">autotesta</a>, Objective-C wypada blado. Należy jednak pamiętać że nie jest to język interpretowany, w którym za pomocą metaprogramistycznych sztuczek możemy zdziałać cuda.</p>
<p>Jednak i na poletku makowych developerów (makowym poletku?) zaczynają pojawiać się rozwiązania wypełniające tą lukę. Bardzo obiecująco wygląda <a href="http://github.com/gabriel/gh-unit/tree/master">GH-Unit</a> dostarczający atrakcyjny interfejs do wykonywania testów i kilka innych ważnych funkcjonalności. W podobnym kierunku idzie <a href="http://www.mcubedsw.com/dev/ocrunner">OCRunner</a> pozwalający z kolei wybierać testy, które chcemy uruchamiać. Przy większej ich ilości, ciągle testowanie całej aplikacji może być dosyć uciążliwe.</p>
<p>Testowanie nie mogłoby się obejść również bez udawanych obiektów &#8211; tutaj z pomocą przychodzi <a href="http://www.mulle-kybernetik.com/software/OCMock/">OCMock</a>.</p>
<p>Jeśli udało mi się zaciekawić Cię tematyką testów w Objective-C, dalej poprowadzą Cię artykuły z poniższych linków:</p>
<p><a href="http://chanson.livejournal.com/tag/unit+testing">http://chanson.livejournal.com/tag/unit+testing</a></p>
<p><a href="http://developer.apple.com/tools/unittest.html">http://developer.apple.com/tools/unittest.html</a></p>
<p><a href="http://code.google.com/p/google-toolbox-for-mac/wiki/CodeVerificationAndUnitTesting">http://code.google.com/p/google-toolbox-for-mac/wiki/CodeVerificationAndUnitTesting</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.macoscope.net/pl/2009/03/testy-jednostkowe-w-objective-c/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Słów kilka o lokalizacji OS X</title>
		<link>http://blog.macoscope.net/pl/2009/02/slow-kilka-o-lokalizacji-os-x/</link>
		<comments>http://blog.macoscope.net/pl/2009/02/slow-kilka-o-lokalizacji-os-x/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 00:12:51 +0000</pubDate>
		<dc:creator>Wojtek Rolecki</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Maktura]]></category>

		<guid isPermaLink="false">http://blog.macoscope.net/pl/?p=143</guid>
		<description><![CDATA[Na długo przed premierą Leoparda w 2007 roku gruchnęła wieść że 10.5 będzie również po polsku. Skazani na lingwistyczną niedolę polscy macuserzy skakali do góry z radości &#8211; wreszcie system po polsku, wreszcie będzie można podarować cioci/babci/dziadkowi Maka (bez konieczności jednoczesnego pełnienia funkcji kogoś w stylu pracownika helpdesku skrzyżowanego z biurem tłumaczeń) i, co doceniali [...]]]></description>
			<content:encoded><![CDATA[<p>Na długo przed premierą Leoparda w 2007 roku <a href="http://blog.fotogenia.info/2007/01/09/a-jednak-bdzie-polski-leopard/">gruchnęła</a> <a href="http://appleblog.pl/105-leopard-bedzie-po-polsku">wieść</a> że 10.5 będzie również po polsku. Skazani na lingwistyczną niedolę polscy macuserzy skakali do góry z radości &#8211; wreszcie system po polsku, wreszcie będzie można podarować cioci/babci/dziadkowi Maka (bez konieczności jednoczesnego pełnienia funkcji kogoś w stylu pracownika helpdesku skrzyżowanego z biurem tłumaczeń) i, co doceniali najbardziej &#8220;hardkorowi&#8221; użytkownicy, wreszcie skończy się hegemonia niedołężnego Polonizatora dodawanego do poprzednich wersji systemu przez polskich resellerów (który, abstrahując od jego wartości dodanej, blokował aktualizacje, uniemożliwiał działanie niektórych aplikacji i inne takie-tam drobne uciążliwości).<br />
<span id="more-143"></span><br />
To tyle historycznego wstępu. Leopard pojawił się w październiku 2007 roku i obyło się bez międzynarodowego skandalu &#8211; miał polską wersję.</p>
<p>Jak to się przedstawia z perspektywy programisty pracującego nad programem przeznaczonym dla konkretnego regionu kulturowo-językowego? Jak wiadomo językiem informatyki nie jest Java, C, Pascal, Perl, ani nawet Visual Basic, tylko&#8230; język angielski. Jako programiści, a więc osoby które generalnie &#8220;umieją komputery&#8221;, 99% czasu spędzamy z systemami i programami których interfejsy są po angielsku. Nadeszła jednak w pewnym momencie taka chwila, że musieliśmy kliknąć w ikonkę International i przestawić nasze Maczydła na język polski. Wszak trzeba się orientować w temacie przed napisaniem interfejsu do polskiego programu, żeby potem nie było &#8220;nie można open&#8221; i tym podobnych historii. Przełączyliśmy, poklikaliśmy &#8211; ogólnie OK, system jest po polsku. W miarę dłubania w kodzie i równoległego obcowania z interfejsem w ojczystym języku wyszło kilka śmiesznych kwiatków w tłumaczeniu OS X&#8217;a. Poniżej kilka z nich.</p>
<p>iTunes, które myśli że AIFF to jakieś urządzenie:</p>
<div id="attachment_132" class="wp-caption aligncenter" style="width: 395px"><img class="size-full wp-image-132" title="Utwórz wersję dla AIFF" src="http://blog.macoscope.net/pl/wp-content/uploads/2009/02/picture-22.png" alt="iTunes dla AIFF PL" width="385" height="165" /><p class="wp-caption-text">Utwórz wersję dla AIFF</p></div>
<p>Bateria, która zdaje się mówić przedwojenną gwarą polsko-jidysz:</p>
<div id="attachment_133" class="wp-caption aligncenter" style="width: 349px"><img class="size-full wp-image-133" title="Baterie jest naładowana" src="http://blog.macoscope.net/pl/wp-content/uploads/2009/02/204695_inmsg.jpg" alt="Baterie" width="339" height="154" /><p class="wp-caption-text">Baterie jest naładowana</p></div>
<p>Model, który myśli że jest modemem (swoją drogą, brzemienny w treść komunikat):</p>
<div id="attachment_134" class="wp-caption aligncenter" style="width: 465px"><img class="size-full wp-image-134" title="Niezgodna wersja modemu" src="http://blog.macoscope.net/pl/wp-content/uploads/2009/02/modemu.png" alt="Core Data model/modem" width="455" height="217" /><p class="wp-caption-text">Model myśli że jest modemem</p></div>
<p>Wiadomo że to pierwsza polska lokalizacja systemu, napięte terminy, tłumacz się zagapił i/lub rozpędził (&#8221;Utwórz wersję dla iPoda&#8221;, &#8220;Utwórz wersję dla Apple TV&#8221;, a więc i &#8220;dla AIFF&#8221;; &#8220;model-modem&#8221; &#8211; <em>same difference</em>), każdemu się może zdarzyć :-)</p>
<p>Ale lokalizacja systemu nie implikuje tylko nowych komunikatów, napisów (&#8221;Okno&#8221; zamiast &#8220;Window&#8221;) i nagłego wydłużenia większości przycisków w elementach UI (&#8221;Reply all&#8221; vs. &#8220;Odpowiedz wszystkim&#8221;) &#8211; jest jeszcze trochę nieoczywistych aspektów – odpowiednie formatowanie liczb (i ich części &#8220;po przecinku&#8221;), kwot w danej walucie (i nazwy walut), formatu dat, nazw dni tygodnia, miesięcy, i tym podobnych. To są rzeczy, z którymi siłą rzeczy musieliśmy mieć do czynienia podczas tworzenia programu do faktur.<br />
 <br />
Na pierwszy strzał poszły nazwy miesięcy &#8211; bomba, ustawiamy polskie <a href="http://en.wikipedia.org/wiki/Locale">locale</a> i wypełniamy menu z terminem płatności, generując daty w pożądanym formacie ([dzień] [miesiąc], [dzień tygodnia]) przy pomocy obiektu klasy <a href="http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html">NSDateFormatter</a>:<br />
 </p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSDateFormatter</span> <span style="color: #002200;">*</span>longDateFormatter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDateFormatter</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>longDateFormatter setLocale<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSLocale</span> alloc<span style="color: #002200;">&#93;</span> initWithLocaleIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pl_PL&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>longDateFormatter setDateFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;d MMMM, EEEE&quot;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>

<p>Odpalamy i&#8230; Szok! <em>Krwawa bójka w posiadłości Angeliny!</em> Khem. To znaczy oglądamy daty i widzimy, że nie dość że są polskie nazwy miesięcy i dni tygodnia, to nawet nie mamy historii typu &#8220;2 luty&#8221;, &#8220;13 grudzień&#8221;, tylko &#8220;2 lutego&#8221;, &#8220;13 grudnia&#8221; i tak dalej. Brawo.</p>
<p>Jedziemy zatem dalej, dojeżdżamy do miejsca, które napawa odrazą wielu programistów &#8211; kwota słownie, czyli sadomasochistyczne historie z polskimi liczebnikami. Długa chwila zadumy nad własnym losem i&#8230; &#8220;Zaraz, gdzieś w panelu Interface Buildera widziałem jakiś number formatter, przy którym było coś o walucie&#8221;. Następnie krótka chwila szaleńczego przeklikiwania się przez interfejs i dokumentację i jest, jest&#8230; uratowani! <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/Reference/Reference.html">NSNumberFormatter</a> ze stylem NSNumberFormatterSpellOutStyle powinien załatwić sprawę:<br />
 </p>

<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #400080;">NSNumberFormatter</span> <span style="color: #002200;">*</span>totalAmountFormatter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumberFormatter</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>totalAmountFormatter setLocale<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSLocale</span> alloc<span style="color: #002200;">&#93;</span> initWithLocaleIdentifier<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;pl_PL&quot;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#91;</span>totalAmountFormatter setNumberStyle<span style="color: #002200;">:</span>NSNumberFormatterSpellOutStyle<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>s <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%@ zł. %@ gr.&quot;</span>,
  <span style="color: #002200;">&#91;</span>totalAmountFormatter stringFromNumber<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">31337</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>,
  <span style="color: #002200;">&#91;</span>totalAmountFormatter stringFromNumber<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span><span style="color: #2400d9;">23</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;     
&nbsp;
NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;słownie: %@&quot;</span>, s<span style="color: #002200;">&#41;</span>;</pre></div></div>

<p> <br />
Kompilujemy, uruchamiamy, przecieramy oczy ze zdumienia:</p>
<p><code>słownie: trzydzieści jeden tysiący trzysta trzydzieści siedem zł. dwadzieścia trzy gr.</code></p>
<p>To działa! Radości nie było końca, a nawet wręcz przeciwnie &#8211; było. Wspólnie ustaliliśmy że słowo &#8220;tysiący&#8221; nie będzie dobrze wyglądać na czyjejś fakturze i wróciliśmy do punktu wyjścia.</p>
<p>Jak widać na załączonych przykładach, drobne błędy w lokalizacji systemu są bardzo zabawne&#8230; dopóki nie trzeba klepać kodu, który robi coś, co można było mieć za darmo. ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.macoscope.net/pl/2009/02/slow-kilka-o-lokalizacji-os-x/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
