<?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>thexpot.net &#187; TDD</title>
	<atom:link href="http://www.thexpot.net/tag/tdd/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thexpot.net</link>
	<description>...olur arada öyle...</description>
	<lastBuildDate>Mon, 18 Jan 2010 13:23:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Etkili Birim Testleri Yazmaaaağğhh!!!</title>
		<link>http://www.thexpot.net/2007/12/etkili-birim-testleri-yazmaaaagghh/</link>
		<comments>http://www.thexpot.net/2007/12/etkili-birim-testleri-yazmaaaagghh/#comments</comments>
		<pubDate>Sun, 30 Dec 2007 18:24:23 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Birçoğumuz <a href="http://en.wikipedia.org/wiki/Agile_development" target="_blank">Agile Development</a>, <a href="http://en.wikipedia.org/wiki/Test_Driven_Development" target="_blank">Test Driven Development</a> (TDD) ve <a href="http://en.wikipedia.org/wiki/Extreme_Programming" target="_blank">Extreme Programming</a> gibi terimleri sıkça duyuyoruzdur. Altlı üstlü bu yöntemlerin tümünün uzlaştığı bir nokta ise yazılımımızın sağlığı için gerekli birim testlerin (Unit Test) yazılmasıdır. 

Peki bu birim testleri nasıl yazmalıyız ki hem etkili olsunlar hem de bakımları kolay olsun?]]></description>
			<content:encoded><![CDATA[<p>Birçoğumuz <a href="http://en.wikipedia.org/wiki/Agile_development">Agile Development</a>, <a href="http://en.wikipedia.org/wiki/Test_Driven_Development">Test Driven Development</a> (TDD) ve <a href="http://en.wikipedia.org/wiki/Extreme_Programming">Extreme Programming</a> gibi terimleri sıkça duyuyoruzdur. Altlı üstlü bu yöntemlerin tümünün uzlaştığı bir nokta ise yazılımımızın sağlığı için gerekli birim testlerin (Unit Test) yazılmasıdır.</p>

<p>Peki bu birim testleri nasıl yazmalıyız ki hem etkili olsunlar hem de bakımları kolay olsun?
Aslında bu sorunun cevabının büyük bir kısmı sizin projenizin tasarımızla ilişkili. Çünkü birim testler adı üzerinde birimleri test etmelidir. Nesne yönelimli programlama (OOP) paradigması ışığında hazırlanmış bir yazılımın birimleri ise sınıflardır. Sınıflarımızı tasarlarken de hayatımızı kolaylaştırması için uymamız gereken belli başlı prensipler var. Mesela her sınıf değişime kapalı fakat genişletilebilirliğe karşı açık olmalıdır ki buna -<a href="http://en.wikipedia.org/wiki/Open/closed_principle" target="_blank">Açık Kapalı Prensibi</a>- denir. vs vs..</p>

<p><span id="more-106"></span>
Duralımda bir soluklanalım derim ben bu noktada. Bütün bu prensipleri biliyoruz da kaçımız uyguluyoruz merak ediyorum. Teori ile pratik arasında dağlar kadar fark olabilir. MFÖ&#8217;nün dediği gibi &#8220;Teori de desen zehir gibi pratik dersen sallanmakta&#8221; da olabilir. Hatta &#8220;fazla teorik bilgi yaratıcılığı öldürür&#8221; de diyebiliriz.</p>

<p>Ben size benim nasıl yazılım geliştirdiğimi anlatayım. Efendim, her şeyden önce yukarıda bahsi geçen metodolojiler, prensipler vs hakkında az çok bilgimizin olması güzeldir, işe yarar. Fakat bunları uygulayacağım diye asıl yapmamız gereken işten uzaklaşmakta pek akıl karı değil. Bundan dolayı ben gidipte bir projeye testleri yazarak başlamam. Önceden tasarım yapıp ta başlamam. Kafamda üstün körü bir tasarım yaparım fakat benim için asıl önemli olan, test edilecek, tasarımı yansıtacak kod olmasıdır. Kod yazarak başlarım ve yazdığım kodun doğru çalışıp çalışmadığını kontrol etmek için test yazarım. Kodu değiştirdikçe testleri de değiştiririm.</p>

<p>Peki diyeceksiniz ki, öyle paldır küldür kod yazamaya başlarsak tasarımımız ne kadar iyi olabilir? Bence her yeni bug çıktığında veya her yeni özellik eklemek istediğinizde sınıflarınızı ve dolayısıyla ilk tasarımınızı değiştirmek zorunda kalırsınız. Bunu hızlı bir şekilde yapabilmek için iyi bir IDE ve iyi bir Refactoring aracı kullanmanız şart. Ben Visual Studio&#8217;yu <a href="http://www.jetbrains.com/resharper/">Resharper</a> olmadan kullanamıyorum. Kodu parçalama bölme değiştirme işlemlerini Resharper ile saniyeler içinde hallediyorum. Bunun verdiği rahatlıkla sınıfları aklıma ilk gelen şekilde yazıyorum. Yazdığım metod bu sınıfa mı ait olmalıymış, adı ne olmalıymış, buraya bir interface tanımlasam daha mı iyi olurmuş diye hiç derdim tasam yok. Kodu yazarım. Oraya interface lazımsa zaten bir sonraki özelliği eklemem gerektiğinde bunun gereğini göreceğim ve Resharper&#8217;a Extract Interface diyeceğim. Metoda oraya ait değilse, Move diyeceğim, adını değiştirmem gerekiyorsa rename diyeceğim. İşime devam edeceğim.
Herkes bir yöntem ortaya atıyor ya, alın size Bug Driven Development! Her bug çıktığında onun için bir test yazarım sonra bug&#8217;ı düzeltirim. Her hatada tasarım daya iyiye gider diyorum o zaman alın size Nature Driven Development!
Uzun sözün kısası; bu prensipleri bilelim ama onlarla kafamızı da bulandırmayalım. Bütün bu prensipleri uygulayacağız diye ortaya bir şey çıkartamıyorsak bir sorunumuz var demektir. Efendim, bazılarınız böyle kod yazmak buglara davetiye çıkarır diyebilir. Tasarım iyi olmazsa ileride daha ciddi problemlerle boğuşulur diyebilir. Ben bu güne kadar, ilk tasarımı ile yıllarca hiç değişmemiş bir kütüphaneye rastlamadım. Her yazılımın illaki hatası olacaktır ve hiç bir tasarım mükemmel çıkmayacaktır. Ne tasarlıyorsanız bugün için tasarlayın. Yeterki ortaya bir şey çıksın.
Bu yazıda olmadı ama ilerki yazılarda yine birim testler, kullanabileceğimiz kütüphanelerden bahsedeceğim ama bunları hangi sıra ve ne sıklıkla kullanacağınız size kalmış. Mutlu yıllar!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2007/12/etkili-birim-testleri-yazmaaaagghh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testlerimiz kodumuzun ne kadarını kapsıyor?</title>
		<link>http://www.thexpot.net/2007/10/testlerimiz-kodumuzun-ne-kadarini-kapsiyor/</link>
		<comments>http://www.thexpot.net/2007/10/testlerimiz-kodumuzun-ne-kadarini-kapsiyor/#comments</comments>
		<pubDate>Tue, 02 Oct 2007 18:20:54 +0000</pubDate>
		<dc:creator>ibrahim dursun</dc:creator>
				<category><![CDATA[Yazılar]]></category>
		<category><![CDATA[Araçlar]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Yazdığımız kodun doğru çalışıp çalışmadığını, istediğimiz özellikleri sağlayıp sağlamadığını testler yazarak garantilemeye çalışırız. Birçok programlama dili için test araçları mevcut, Delphi için <a href="http://dunit.sourceforge.net/" targer="_blank">DUnit</a>, java için <a href="http://www.junit.org/" target="_blank">JUnit</a>, .Net için <a href="http://www.nunit.org/" target="_blank">NUnit</a>, <a href="http://www.mbunit.com/" target="_blank">MbUnit</a> vs... Fakat yazdığımız bu testlerin kodumuzun ne kadarını test ettiğini, hiç atladığımız durumlar olup olmadığını merak etmiyor musunuz? İşte bunun içinde başka bir araç var ve adı <a href="http://ncover.org/" target="_blank">NCover</a>. 
<h3>Kod Kapsama nedir?</h3>
Testlerimizin kodun ne kadarına uğradığını ve dolayısıyla tümüne oranla ne kadarlık kod parçasının testlere dahil olduğunu ölçmek için kullanılan kalite kontrol yöntemi "Code Coverage" <i>(Kod Kapsama)</i> diye adlandırılır. 

Kod kapsama ile ne gibi bir ölçüm yaparız?
<ul>
<li>Test senaryolarımız tarafından ulaşılmayan, test edilmeyen kod parçacıklarını tespit edebiliriz
<li>Test edilmeyen kod parçalarını da içerecek yeni testler yazabilir ya da eski testlerimizi genişletebiliriz.
<li>Gereksiz testleri tespit edip kaldırabiliriz.
<li>Aslında hiç kullanmadığımız kod parçacıklarını ayıklayabiliriz
</ul>

Ben Visual Studio için <a href="http://www.testdriven.net/" target="_blank">TestDriven.Net</a> eklentisi kullanıyorum ve bu eklenti ile hazır NCover desteği de geliyor ki işimizi fazlasıyla kolaylaştırıyor. TestDriven.Net, kişisel kullanım için ücretsiz, fakat Visual C# Express Edition kullanıyorsanız bu eklentiden faydalanamazsınız çünkü Express Editionlar eklenti yüklenmesine izin vermiyor. <strike>Başka bir alternatif ise JetBrains'in <a href="http://www.jetbrains.com/unitrun/" target="_blank">UnitRun</a>'ı ki bu üründe ücretsiz.</strike>

Diyelimki bir tane <em>Registration</em> adında bir DTO sınıfınız ve bu sınıftaki bilgileri doğrulayan <em>RegistrationValidator</em> diye başka bir sınıfız var.]]></description>
			<content:encoded><![CDATA[<p>Yazdığımız kodun doğru çalışıp çalışmadığını, istediğimiz özellikleri sağlayıp sağlamadığını testler yazarak garantilemeye çalışırız. Birçok programlama dili için test araçları mevcut, Delphi için <a href="http://dunit.sourceforge.net/">DUnit</a>, java için <a href="http://www.junit.org/" target="_blank">JUnit</a>, .Net için <a href="http://www.nunit.org/" target="_blank">NUnit</a>, <a href="http://www.mbunit.com/" target="_blank">MbUnit</a> vs&#8230; Fakat yazdığımız bu testlerin kodumuzun ne kadarını test ettiğini, hiç atladığımız durumlar olup olmadığını merak etmiyor musunuz? İşte bunun içinde başka bir araç var ve adı <a href="http://ncover.org/" target="_blank">NCover</a>.
<h3>Kod Kapsama nedir?</h3>
Testlerimizin kodun ne kadarına uğradığını ve dolayısıyla tümüne oranla ne kadarlık kod parçasının testlere dahil olduğunu ölçmek için kullanılan kalite kontrol yöntemi &#8220;Code Coverage&#8221; <em>(Kod Kapsama)</em> diye adlandırılır.</p>

<p>Kod kapsama ile ne gibi bir ölçüm yaparız?
<ul>
    <li>Test senaryolarımız tarafından ulaşılmayan, test edilmeyen kod parçacıklarını tespit edebiliriz</li>
    <li>Test edilmeyen kod parçalarını da içerecek yeni testler yazabilir ya da eski testlerimizi genişletebiliriz.</li>
    <li>Gereksiz testleri tespit edip kaldırabiliriz.</li>
    <li>Aslında hiç kullanmadığımız kod parçacıklarını ayıklayabiliriz</li>
</ul>
Ben Visual Studio için <a href="http://www.testdriven.net/" target="_blank">TestDriven.Net</a> eklentisi kullanıyorum ve bu eklenti ile hazır NCover desteği de geliyor ki işimizi fazlasıyla kolaylaştırıyor. TestDriven.Net, kişisel kullanım için ücretsiz, fakat Visual C# Express Edition kullanıyorsanız bu eklentiden faydalanamazsınız çünkü Express Editionlar eklenti yüklenmesine izin vermiyor. <span style="text-decoration: line-through;">Başka bir alternatif ise JetBrains&#8217;in <a href="http://www.jetbrains.com/unitrun/" target="_blank">UnitRun</a>&#8216;ı ki bu üründe ücretsiz.</span></p>

<p>Diyelimki bir tane <em>Registration</em> adında bir DTO sınıfınız ve bu sınıftaki bilgileri doğrulayan <em>RegistrationValidator</em> diye başka bir sınıfız var.
<span id="more-95"></span>
<pre class="prettyprint">
public class Registration
{
  string name;
  string password;
  public string Name
  {
    get { return name; }
    set { name = value; }
  }
  public string Password
  {
    get { return password; }
    set { password = value; }
  }
}
public class Validator
{
  public const int MIN<em>PASSWORD</em>LENGTH = 6;
  public const int MIN<em>NAME</em>LENGTH = 5;
  protected virtual bool IsValidUserName(Registration registration)
  {
    return registration.Name.Length > MIN<em>NAME</em>LENGTH;
  }
  protected virtual bool IsValidPassword(Registration registration)
  {
    return
      registration.Password.Length > MIN<em>PASSWORD</em>LENGTH &amp;&amp;
      registration.Password.IndexOfAny("0123456789".ToCharArray())>-1;
  }
  public virtual bool IsValid(Registration registration)
  {
    return IsValidUserName(registration) &amp;&amp; IsValidPassword(registration);
  }
}</pre>
Testlermizi de yazmışız:
<pre class="prettyprint">
[TestFixture]
public class ValidationTests
{
  private Validator <em>validator = new Validator();
  private Registration _registration;
  [SetUp]
  public void SetUp()
  {
    _registration = new Registration();
    _registration.Name = "t-hex";
    _registration.Password = "abcd";
  }
  [Test]
  public void Should</em>not<em>validate</em>if<em>name</em>is<em>shorter</em>than<em>minumun</em>length()
  {
    Assert.IsFalse(<em>validator.IsValid(</em>registration));
  }
  [Test]
  public void Should<em>not</em>validate<em>if</em>password<em>doesnt</em>contain<em>numbers()
  {
    Assert.IsFalse(</em>validator.IsValid(<em>registration));
  }
  [Test]
  public void Should</em>not<em>validate</em>if_password__is_shorter_than_minimum_length()
  {
    Assert.IsFalse(_validator.IsValid(_registration));
  }
}</pre>
Buraya kadar her şey güzel, testlerimizi çalıştırdık ve beklediğimiz sonucu aldık.
<code>
3 passed, 0 failed, 0 skipped, took 0,42 seconds.
</code></p>

<p>Peki gerçekten doğru mu yaptık? Bir de NCover ile bakalım:<br />
<img src="http://www.thexpot.net/img/95_ncover1.png" alt="" />
Neden oranlar bu kadar düşük? 100% olması lazım zaten iki üç tane metodu test ediyoruz burada. Hatta sonuçlardan anladımıza göre <em>get_Password</em>, <em>IsPasswordValid</em> metodları hiç çağırılmamış!</p>

<p>Bunun nedeni lazy evaluation. C# derleyicisi tümü &#8220;ve&#8221; ile bağlanmış bir ifade de ilk false döndükten sonrakileri hiç çalıştırmaz çünkü zaten her durumda tüm sonuç false olacaktır. Bu durumda da biz ilk testi yaptığımızda uzunluk 5 karakterden kısa olduğu için false alıyoruz ve aslında şifreyi hiç kontrol etmiyoruz. Hatta daha vahimi ise şifreyi test eden kodumuzu gerçektende yanlış yazmışız, IndexOfAny metodu -1&#8242; eşit değil -1&#8242;den büyük olmalıydı.</p>

<p>Kodumuzu düzeltelim:
<pre class="prettyprint">
protected virtual bool IsValidPassword(Registration registration)
{
  bool valid = registration.Password.Length > MIN<em>PASSWORD</em>LENGTH;
  valid = valid &amp;&amp; registration.Password.IndexOfAny("0123456789".ToCharArray()) > -1;
  return valid;
}
//testlerde de
[Test]
public void Should<em>not</em>validate<em>if</em>password<em>doesnt</em>contain<em>numbers()
{
  _registration.Name = "longername";
  _registration.Password = "abcdefg";
  Assert.IsFalse(</em>validator.IsValid(_registration));
}</pre>
Çalıştıralım ve 100% kapsamayı görelim.</p>

<p>Burdan 2 sonuç çıkarabiliriz:
Birincisi; Test edilmesi gereken koşulların hepsini &#8220;ve&#8221; ile bağlamayın, bu hem okunurluğu azaltır, hem de yukarıdaki gibi hatalara neden olabilir. Onun yerine önce boolean değişkenlere değerleri atayın sonra kontrol edin.
İkincisi de hiçbir zaman emin olmayın.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thexpot.net/2007/10/testlerimiz-kodumuzun-ne-kadarini-kapsiyor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
