wtorek, 1 kwietnia 2008

TestNG - dane testowe z plików XML

Pisząc artykuł TestNG - dostawca danych przypomniałem sobie o pewnym mini framework'u do wykonywania testów jednostkowych, który przyszło mi kiedyś napisać. Musiałem go napisać nie dlatego, że w projekcie nie znano jUnita ;) ale dlatego, że jUnit w pewnych przypadkach nie wiele pomagał. Konkretnie chodzi o sytuację gdy wiele testów ma ten sam algorytm, a różnią się między sobą danymi testowymi (czasami są to dość duże zestawy danych).
Moim zdaniem w takim przypadku warto oddzielnie zarządzać danymi i algorytmami testowymi i umiejscowić je w różnych plikach. Wówczas istnieje możliwość, aby dane testowe przygotowywała inna osoba niż autor algorytmów testowych, nie trzeba ponownie kompilować testów gdy się zmieniły dane, no i łatwiej można uniknąć problemów z kodowaniem danych wejściowych.

DataProvider w TestNG nie wspiera bezpośrednio zaczytywania danych testowych z plików XML. Ale jak się okazało, robienie tego samemu nie jest trudne i co najważniejsze nie wymaga znaczących nakładów kodowania. Wystarczy zastosować dostarczaną przez specyfikacje J2SE serializację XML JavaBean'ów.
Schema serializacji jest relatywnie zrozumiała dla ludzi, a co najważniejsze jest bardzo elastyczna. Schema ta dopuszcza zapisywanie dowolnej liczby dowolnych obiektów. Ponadto można łatwo wygenerować przykładowy plik wejściowy do testów, poprzez zserializowanie spreparowanych w kodzie przykładowych danych.

Poniżej zamieszczam przykładową zawartość pliku XML z danymi testowymi:
<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.5.0" class="java.beans.XMLDecoder">
 <array>
  <string>test1</string>
  <object class="pl.dwalczak.testngdp1.User">
   <void property="nickName">
    <string>heniek</string>
   </void>
   <void property="address">
    <object class="pl.dwalczak.testngdp1.Address"
     id="addr1">
     <void property="city">
      <string>Poznań</string>
     </void>
     <void property="postcode">
      <string>11-111</string>
     </void>
     <void property="street">
      <string>Jadwigi</string>
     </void>
     <void property="number">
      <string>11a/3</string>
     </void>
    </object>
   </void>
   <void property="mailingAddress">
    <object idref="addr1" />
   </void>
  </object>
 </array>
 <array>
  <string>test2</string>
  <object class="pl.dwalczak.testngdp1.User">
   <void property="nickName">
    <string>maniek</string>
   </void>
   <void property="address">
    <object idref="addr1" />
   </void>
   <void property="mailingAddress">
    <object idref="addr1" />
   </void>
  </object>
 </array>
</java>
Natomiast implementacja TestNG'owego data providera, korzystającego z tego pliku XML, może wyglądać następująco:
package pl.dwalczak.testngdp1;
import java.beans.XMLDecoder;
import java.io.FileInputStream;
import java.util.ArrayList;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

@Test
public class SimpleTest {
 
 @DataProvider(name="dp")
 public Object[][] createData() {
  ArrayList<Object[]> result = new ArrayList<Object[]>();
  XMLDecoder dec = null;
  try {
   dec = new XMLDecoder(new FileInputStream("testData.xml"));
   while (true) {
    Object o = dec.readObject();
    result.add((Object[]) o);
   }
  } catch (ArrayIndexOutOfBoundsException e) {
   // no more objects in stream
  } catch (Exception e) {
   throw new RuntimeException(e);
  } finally {
   if (dec != null) {
    dec.close();
   }
  }
  
  return result.toArray(new Object[result.size()][]);
 }

 @Test(dataProvider="dp")
 public void test(String arg0, User user) {
  System.out.println("arg0: " + arg0);
  System.out.println("user: " + user);
 }
}

Zasoby

Pliki źródłowe przykładu
Long Term Persistence of JavaBeans Components: XML Schema
Dokumentacja TestNG - 5.5.2 - From DataProviders

Brak komentarzy: