Mariusz Prowaźnik

o programowaniu w Javie, Scali i Clojure.


Kategorie w testach JUnit

Dobrze zaprojektowany test jednostkowy powinien testować jedną klasę, z zaślepionymi zależnościami (np z EasyMock) i wykonywać się szybko, żeby nie było pokusy ich omijania. Uruchamiając je przy każdym buildzie aplikacji wychwytuje się szybko wiele błędów regresji, co oszczędza dużo czasu.

Jednak JUnit, choć przeznaczony jest głównie do testów jednostkowych, można użyć również do bardziej złożonych testów: integracyjnych, lub wydajnościowych, które wykonuje się rzadziej niż jednostkowe. Tylko trzeba by je jakoś oddzielić od siebie, np. pogrupować w kategorie i stworzyć zestawy (TestSuite) które będą wykonywać poszczególne grupy testów. Wtedy przydatna okazuje się adnotacja @Category, która określa kategorię testu. Kategorią może być dowolna klasa, lub interfejs. Przykładowo:
public interface SlowTest {}
public interface FastTest {}
stworzyłem dwa interfejsy, które użyję jako kategorie testów:
public class SimpleTest {
    @Category(FastTest.class)
    @Test
    public void someTest() {
        // ...
    }

    @Category(SlowTest.class)
    @Test
    public void someTest() {
        // ...
    }
}
oraz TestSuite, w którym oprócz klas testowych określam kategorię testów, jaką ma wykonać:
@RunWith(Categories.class)
@IncludeCategory(FastTests.class)
@SuiteClasses({ SimpleTest.class })
public class SimpleTestSuite {
}
Adnotacją @Category można oznaczać poszczególne metody lub całe klasy. Powyższy przykład wykonuje testy oznaczone kategorią FastTests.class. Odwrotne zachowanie nastąpi po użyciu adnotacji @ExcludeCategory(FastTest.class).

W eclipse można skonfigurować sobie czy mają być wykonywane wszystkie testy, czy na przykład tylko wybrany zestaw (Run Configurations -> JUnit). Myślę, że dosyć wygodnym rozwiązaniem jest stworzyć sobie dwie konfiguracje, jedną uruchamiającą zestaw (TestSuite) z testami o kategorii FastTests i drugą uruchamiającą zestaw z wszystkimi testami.

Project Lombok - skróć kod o 90%

Ten post jest o pomysłowym i bardzo prostym narzędziu, które pozwala uporać się z jedną z javovych niedogodności.

Załóżmy, że potrzebujesz klasy Punkt, z dwoma polami typu double. Aby było zgodnie z dobrymi praktykami programowania, pola będą miały dostęp prywatny, wygenerujesz gettery i settery, konstruktor, toString, equals i hashCode, przez co kod klasy urośnie do rozmiaru 965 znaków:
public class Punkt {
 private final double x;
 private final double y;

 public Punkt(double x, double y) {
  super();
  this.x = x;
  this.y = y;
 }

 @Override
 public String toString() {
  return "Punkt [x=" + x + ", y=" + y + "]";
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  long temp;
  temp = Double.doubleToLongBits(x);
  result = prime * result + (int) (temp ^ (temp >>> 32));
  temp = Double.doubleToLongBits(y);
  result = prime * result + (int) (temp ^ (temp >>> 32));
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Punkt other = (Punkt) obj;
  if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
   return false;
  if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
   return false;
  return true;
 }

 public double getX() {
  return x;
 }

 public double getY() {
  return y;
 }
Co prawda kod ten generuje IDE, ale czy nie wolałbyś, żeby klasa Punkt wyglądała na przykład tak:
import lombok.Data;
public @Data class Punkt {
 private final double x;
 private final double y;
}
To 94 znaków zamiast 965. Jak dla mnie pomysł świetny. Na stronie http://projectlombok.org/ jest 3 minutowy filmik, po obejrzeniu którego nie będzie problemu z użyciem we własnym projekcie.