Perşembe, Ağustos 16, 2007

EMMA ile Code Coverage

Yazılım Geliştirme sürecindeki en önemli adımlardan biri de testleri tamamlanan uygulamanın gerçek (production) ortamda devreye alınmasıdır. Bir uygulamanın gerçek ortam için hazır olup olmadığını belirleyen en önemli kriterlerin başında test sonuçları gelir. Klasik yazılım geliştirme metodolojilerinde, Test Yöneticisinin tüm testlerin başarıyla geçtiği bilgisini vermesi, yeşil ışığın yanması için yeterlidir. Hatta Test bölümüne "Tüm ekranları test ettiniz değil mi?" diye sorulduğunda genelde şu cevap alınır; "Tabii ki..., her ekranda birer işlem bile yaptık."
Buna rağmen gerçek ortamda bir sürü hata ortaya çıkmaya başlar, bunları sebebi sorulduğunda ise bahane hazırdır: "Biz o senaryoyu test etmemiştik". Peki nasıl olur da bir yazılımın ne kadarının test edildiğini, tamamen objektif değerler ile tespit edebiliriz? Tabii ki "Code Coverage" diye adlandırılan araçlarla.
İşte bu blogumda özellikle java dünyasında çok kullanılan, açık kaynak kodlu "Code Coverage" araçlarından biri olan EMMA'dan bahsedeceğim. EMMA kabaca, Java tabanlı uygulamaların test edildiklerinde, kod parçalarının (sınıf, metot, blok ve satır bazında) ne kadarının kullanıldığını raporlar.
Örneğin bu linkteki EMMA ile hazırlanmış Apache Velocity uygulamasına ait, html formatındaki "Code Coverage" raporunu inceleyecek olursanız, unit testler sonrasında hangi kod, ne oranda test edilmiş rahatlıkla görebilirsiniz. Sınıf bazında detaya bakacak olursanız kodlarda tamamen geçilen yerlerin yeşil, bir kısmından geçilenlerin sarı, hiç uğranılmayan yerlerin kırmızı ile renklendirildiğini farkedeceksiniz.

  • EMMA ile yukarıdaki örnekteki raporu üretebilmeniz için öncelikle java kodlarınızın (*.class) basit bir işlemden geçmesi gerekmektedir. Bu işlemin "off-line" ve "on-the-fly" olmak üzere 2 yöntemi vardır. Uygulamanın tipine (stand-alone, web, vs.) göre bu yöntemlerden biri seçilir.
  • EMMA, raporlarını HTML, XML veya text formatında üretebilir. Ayrıca HTML raporu uygulamanın kaynak kodları ile ilişkilendirilebilir.
  • EMMA java uygulamasını işlemek için kaynak kodlara ihtiyaç duymaz. Açık bir klasördeki *.class dosyalarını veya *.jar içindeki class'ları kullanabilir. Kaynak kodlar sadece html raporlarında ekstra bir güzellik sağlar.
  • EMMA çok az kaynak tüketerek ve hızlı bir şekilde çalışır. Ayrıca JDK 1.2.x ve üstünü destekler.
  • EMMA'nın en güzel özelliklerinden biri de kullanımı çok kolay bir Apache Ant task'ının olmasıdır.
Aslında EMMA'nın daha bir çok mahareti mevcut, fakat benim tavsiyem kafanızdaki diğer sorulara da cevap bulabilmeniz amacıyla Sık Sorulan Sorular bölümüne bir göz atmanız. Bu bölümde EMMA gayet özet ve güzel bir şekilde anlatılmış.
Şimdi de EMMA ile bir deneme sürüşü yapalım:
  • Öncelikle bu linkten EMMA'yı bilgisayarınıza indirin. Eğer sadece EMMA'yı çalıştırmak için gerekli dosyaları indirmek istiyorsanız emma-X.Y.Z-lib.zip formatındaki dosyayı indirin ve bilgisayarınızda her hangi bir yere açın. Benim bilgisayarımda EMMA, "D:\Programs\emma-2.0.5312" altında kurulu.
  • EMMA'yı çalıştırmak için bilgisayarınızda Java'nın yüklü olması yeterlidir. EMMA çalışmak için başka bir kütüphaneye ihtiyaç duymaz.
  • Örneğimizde ilk olarak EMMA'nın "on-the-fly instrumentation" yöntemini kullanacağız. Ardından "off-line instrumentation" yöntemini kullanarak aynı örneği tekrarlayacağız.
  • Öncelikle EMMA'dan geçireceğimiz uygulamayı seçiyoruz. Bu örnekte iki zip formatındaki (jar,war,ear, vs.) dosyanın farkını gösteren harika bir açık kaynak uygulama olan zipdiff'i kullanacağız.
  • EMMA ile "Code Coverage" yapmıyor olsaydık, zipdiff kullanarak iki farklı versiyondaki log4j.jar dosyasının html raporu şeklinde farkını şu şekilde alıyor olacaktık:
>java -jar zipdiff.jar -file1 log4j-1.2.8.jar -file2 log4j-1.2.13.jar -outputfile diffs.html

Şimdi de aynı uygulamayı EMMA ile birlikte çalıştıralım:

on-the-fly instrumentation

On-the-fly yöntemi daha çok standalone çalışabilen uygulamalar için tercih edilmektedir. Bu yöntem ile tek bir seferde "Code Coverage" raporu elde edilebilmekte, java uygulaması EMMA üzerinden çalışmaktadır.
Uygulamayı çalıştırdığımızda da şöyle bir sonuç alıyoruz:

>java -cp D:\Programs\emma-2.0.5312\lib\emma.jar emmarun-r html -sp src\main -jar zipdiff.jar -file1 log4j-1.2.8.jar -file2 log4j-1.2.13.jar -outputfile diffs.html
>File 1 = log4j-1.2.8.jar
>File 2 = log4j-1.2.13.jar
>EMMA: writing [html] report to [D:\Programs\zipdiff-0.4\coverage\index.html] ...

Yukarıdaki komutu çalıştırdığımızda EMMA "coverage" isminde bir klasör yaratacak ve html formatındaki raporu bu klasör içinde oluşturacaktır. Eğer yukarıdaki komut satırında "-r html" parametresini kullanmasaydık rapor text formatında olacaktı. Ayrıca "-sp" parametresi ile zipdiff uygulamasının kaynak kodlarını EMMA'ya göstermiş olduk.



On-the-fly instrumentation çok basit olmasına rağmen performansı az da olsa düşürmekte:
the runtime overhead of added instrumentation is small (5-20%) and the bytecode instrumentor itself is very fast (mostly limited by file I/O speed). Memory overhead is a few hundred bytes per Java class.
off-line instrumentation

Off-line yöntemi daha çok JSP,Servlet,EJB gibi Uygulama Sunucularında çalışan uygulamalar için tercih edilen bir yöntemdir. Zaten EMMA'nın Sık Sorulan Sorular bölümünde bunun sebebi ve Tomcat, Weblogic, WebSphere, vs. gibi Uygulama Sunucuları ile nasıl kullanılacağı adım anlatılmış:
How do I use EMMA in {WebLogic, Websphere, Tomcat, JBoss, ...}?
First of all, there is little chance that you will be able to use the on-the-fly mode (emmarun) with a full-blown J2EE container. The reason lies in the fact that many J2EE features require specialized classloading that will happen outside of EMMA instrumenting classloader. The server might run fine, but you will likely get no coverage data.

Thus, the correct procedure is to instrument your classes prior to deployment (offline mode). Offline instrumentation always follows the same compile, instrument, package, deploy, get coverage, generate reports sequence. Follow these steps...
Şimdi yukarıdaki örneği off-line yöntemi ile yapalım. Bu yöntemde "-overwrite" parametresi kullanacağımız için siz de benzer örneği yaparken uygulamanızın (jar dosyasının) bir yedeğini almayı unutmayın. Çünkü EMMA off-line yöntemde tüm class'ları değiştirmektedir.
Öncelikle uygulamamızı (zipdiff.jar) bir EMMA'dan geçiriyoruz:

>java -cp D:\Programs\emma-2.0.5312\lib\emma.jar emma instr -m overwrite -cp zipdiff.jar
>EMMA: processing instrumentation path ...
>EMMA: instrumentation path processed in 359 ms
>EMMA: [27 class(es) instrumented, 10 resource(s) copied]
>EMMA: metadata merged into [D:\Programs\zipdiff-0.4\coverage.em] {in 47 ms}

Yukarıdaki komutu çalıştırdığımızda coverage.em isimli bir dosya elde ediyoruz. Bu dosyayı daha sonra raporu oluşturmak için kullanacağız. Ardından uygulamamızı çalıştıracağız fakat bu sefer EMMA üzerinden değil de klasik yöntemle başlatacağız. Sadece fazladan classpath'e emma.jar dosyasını da ekleyeceğiz:

>java -cp D:\Programs\emma-2.0.5312\lib\emma.jar;zipdiff.jar zipdiff.Main -file1 log4j-1.2.8.jar -file2 log4j-1.2.13.jar -outputfile diffs.html
>EMMA: collecting runtime coverage data ...
>File 1 = log4j-1.2.8.jar
>File 2 = log4j-1.2.13.jar
>EMMA: runtime coverage data merged into [D:\Programs\zipdiff-0.4\coverage.ec] {in 62 ms}

Uygulamamızı da çalıştırdık ve bu sefer de coverage.ec isminde bir dosya elde ettik. Şimdi de coverage.em ve coverage.ec dosyalarını kullanarak raporumuzu üretelim:

>java -cp D:\Programs\emma-2.0.5312\lib\emma.jar emma report -r html -sp src\main -in coverage.em,coverage.ec
>EMMA: processing input files ...
>EMMA: 2 file(s) read and merged in 15 ms
>EMMA: writing [html] report to [D:\Programs\zipdiff-0.4\coverage\index.html] ...

Komut satırından çalıştırılan yukarıdaki benzer basit örnekleri EMMA'nın Quick Start sayfasından, detaylıları da User Guide'dan bulabilirsiniz. Ayrıca EMMA'nın Apache Ant task'ları da mevcut. Ant task'ları kullanarak Uygulama Sunucuları için hazırlanmış derleme ve test scriptlerini de ayrıca hazırlayıp burada paylaşacağım. Bu arada biz EMMA'yı Weblogic ile gayet başarılı bir şekilde kullanıyoruz.
Şimdilik benden bu kadar :)

Etiketler: ,

4 Yorum:

Anonymous Adsız dedi ki...

Selamlar

Gayet detaylı bir EMMA yazısı olmuş. Yazıyı okuyunca aklıma daha evvel Cenk Çivicinini yazmış olduğu bu yazı geldi.

Test yaptık herşey süper dememek ve kontrolü elden bırakmamak lazım. Yine de EMMA 'nın TDD için çok faydalı bir araç olduğunu da eklemekte fayda var.

Şimdilik benden de bu kadar :)

1:41 ÖS  
Blogger Mustafa Tan dedi ki...

Selam İbrahim,

Cenk'in bahsettiği gibi assertion konmazsa tabii ki Code Coverage tek başına anlam ifade etmez.

Fakat assertion yapılmasa dahi uygulama eğer exception'a düşüyorsa CodeCoverage'taki block ve line yüzdesi düşük çıkacaktır. Çünkü try blokları catch bloklarına oranla daima daha fazla yer kaplar.

Bir üçkağıt varsa dahi EMMA yakalayacaktır. :)

6:04 ÖS  
Anonymous Adsız dedi ki...

Selam Mustaf Abi;

Az önce Code Coverage konusuyla ilgili inceleme yaparken .NETci bir arkdaşın Code Coverage macerasına denk geldim.
Coverage konusunda kadranı dibe vurdurmuş (%100 :) ) bir arkadaş ve bu konuda neler yaptığını, .NET platformu için hangi araçlardan faydalnadığını açıklamış. Blogunu takip edenler için faydalı olabileceğini inandığım Advocating the use of code coverage yazısını paylaşmak istedim.

Kolay gelsin.

6:47 ÖÖ  
Anonymous Adsız dedi ki...

Selamlar Mustafa Abi;

Fırsat buldukça bu yazıyı hergün okuyorum :) aklıma takılan bir soru oldu. Acaba EMMA 'dan yada önerebileceğin başka bir tooldan Functional Testlerde de faydalanabilir miyiz?

Şöyleki testi yapacak vatandaş ekrandan ne kadar zorlarsa o kadar çok kod taranacaktır. Bu durumda eğer yeterince iyi Funvtional Test yapılmışsaa koddaki fazlalıklar da belirgin hale gelir diye düşünüyorum. (Hiç oluşmayacak bir if kontrolu yada boş here handle edilmiş exception)Run time sırasında bu tip birşey yapmak mümkün müdür?

Kolay gelsin.

10:58 ÖÖ  

Yorum Gönder

Kaydol: Kayıt Yorumları [Atom]

<< Ana Sayfa