News Radar: Minimalny użyteczny projekt Scalowy

Ten weekend napewno nie upłynie pod znakiem wzmożonego kodowania, ale zaplanowałem, że przygotuję sobie absolutne minimalny użyteczny projekt, tak żeby po weekendzie skupić się już na pierwszych funkcjonalnościach. To minimum to projekt budowany w SBT z przykładową klasą i przykładowym testem w ScalaTest, który będzie budowany na Travisie.

Najpierw pusty projekt. Najbardziej oczywistym wyborem jest użycie SBT jako build toola. W SBT domyślnie projekt układa się dość podobnie jak w Mavenie:

  • src/main/java na klasy Javowe
  • src/main/scala na klasy Scalowe
  • src/main/resources na „zasoby”
  • test/main/java na testy Javowe
  • test/main/scala na testy Scalowe
  • test/main/resources na „zasoby” do testów

Sercem SBT jest plik build.sbt – zawiera on w sobie opis całego projektu  (Co ciekawe opis ten sam w sobie pisze się w Scali). W swojej najmniejszej formie można tam zdefiniować nazwę projektu, jego wersję i wersję Scali, której używamy:

name := "news-radar"
version := "1.0"
scalaVersion := "2.11.7"

Ja swój projekt wygenerowałem z użyciem InteliJ, który ma w sobie już wbudowane SBT, ale ponieważ wydaję mi się, że warto jednak mieć możliwość używania SBT w lini komend (co zresztą za chwilę postararm się udowowdnić), więc ja sobie go jeszcze zainstalowałem lokalnie. W OS X sprowadza się to do użycia homebrew:

 brew install sbt 

Mając już gotowy projekt warto pokusić się o jakiegoś hello worlda:

class HelloWorld {
  def helloWorld() : String = {
    "Hello, Daj sie poznac!"
  }
}

Nie robię klasycznego printowania, ponieważ cel, który chcę osiągnąć to prosty test jednostkowy, który sprawdzi, czy String zwracany z tej klasy jest poprawny.

Do testów jednostkowych postanowiłem użyć biblioteki ScalaTest. Dodanie takiej zależności do projektu przez SBT jest tak samo proste jak w Mavenie. Modyfikujemy plik build.sbt dodając linijki:

lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.1" % "test"
libraryDependencies += scalaTest

Pierwsza linijka tworzy wartość zawierającą definicję biblioteki ScalaTest w wersji 3.0.1 – jest ona dołączona jako test dependency. W drugiej linijce, naszą zależność podczepiamy pod kolekcję libraryDependencies – jest to wewnętrzna kolekcja SBT w której właśnie defnicje wszystkich zależności z których chcemy korzystać.

Po zaciągnięciu zależności możemy przystąpić do napisania szybkiego teściku:

class HelloWorldTest extends FlatSpec with Matchers {
  "Hello world example" should "return hello world string" in {
    val hw = new HelloWorld
    hw.helloWorld() should be ("Hello, Daj sie poznac!")
  }
}

I teraz jeden z argumentów dlaczego warto mieć SBT zainstalowane lokalnie. W InteliJ możemy sobie odpalić taki test w taki sam sposób jak testy JUnit w Javie. Ja jednak w projektach Javowych używałem pluginu infinitest, który automatycznie odpalał testy po wykryciu zmian w projekcie. Coś podobnego możemy uzyskać z konsolą SBT. Otwórzmy w InteliJ terminal (View -> Tool Windows -> Terminal). Żeby uruchomić konsolę SBT należy wydać komendę o takiej samej nazwie:

sbt

W tym momencie jesteśmy w konsoli sbt. Jako że Intelij otworzył terminal w katalogu z projektem, to konsola SBT będzie pracować na naszym projekcie. Żeby skompilować projekt możemy wydać polecenie

compile

Dla „zwykłego” wywołania testów używamy

test

I teraz fajna część. Jeżeli jakąś komendę w SBT poprzedzimy znakiem tyldy, to SBT będzie nasłuchiwać na zmiany w plikach projektu i automatycznie jeszcze raz wywoła naszą komendę. Zatem aby mieć continous testing wydajemy polecenie:

~test

I możemy kodować dalej mając pewność, że SBT przywoła nas do porządku w momencie popsucia testów :)

Ostatnią rzeczą, którą warto mieć to continious integration. Ja zdecydowałem się na skorzystanie z Travisa, ponieważ dla open source projektów z Githuba, możemy użyć tego narzędzia za darmo. Aby to zrobić trzeba się zalogować do Travisa i pozwolić mu na dostęp do swojego konta na Githubie. Następnie z poziomu Travisa szukamy na liście projektów tego dla którego chcielibyśmy mieć CI i go „włączamy”.

Domyślnie Travis jest w stanie wystartować bez swojego pliku konfiguracyjnego, ale może to nie być najlepszym pomysłem. Dlatego też dodajmy sobie plik .travis.yml do roota naszego projektu – zdefiniujmy narazie tylko absolutnie podstawowe rzeczy:

language: scala
scala:
- 2.11.7

Zdefiniowaliśmy, że nasz projekt jest napisany w Scali, więc Travis po swojej stronie użyje SBT. Zdefiniowaliśmy też, że chcemy budować projekt używając wersji 2.11.7 Scali (moglibyśmy wyszczególnić więcej wersji, jeśli np. chcielibyśmy testować czy w różnych wersjach języka nasza aplikacja dalej działa). I już – od tej pory po każdym pushu Travis zaciągnie sobie zmiany i zbuduje projekt. Jeśli build zakończy się niepowodzeniem to Travis może być tak skonfigurowany, żeby wysłać nam o tym maila.

Bardzo często używanym ficzerkiem Travisa jest możliwość wstawienia sobie prostego badge’a, który będzie nam pokazywać czy build się udał- będzie on wyglądał o tak: Status Buildu

Podsumowując. W kilka minut stworzyliśmy sobie minimalny, użyteczny projekt Scalowy:

  • Mamy projekt w SBT.
  • Mamy przykładową klasę.
  • Mamy dodane zależności do ScalaTest i prościutki test napisany z wykorzystaniem tej biblioteki.
  • Wiemy też jak za pomocą konsoli SBT sprawić sobie proste continious testing.
  • Wiemy jak niskim kosztem zorganizować sobie Continious Integeration za pomocą Travisa.

Na dzisiaj to tyle :)

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *