Dart: continuous integration con Drone.io

Di - 2 March 2013 - in

Ogni applicazione o libreria che si rispetti dovrebbe essere sempre accompagnata da una serie di unit test che ne provino la stabilità e la affidabilità. Nell’articolo di oggi vedremo come sviluppare dei test per una libreria di esempio, avvalendoci della libreria unittest, e come utilizzare il servizio gratuito di continuous integration offerto da Drone.io.

Cominciamo sviluppando la nostra libreria di esempio: una classe, Carta, che rappresenta una carta da gioco francese.

Apriamo il Dart Editor, creiamo una nuova applicazione e togliamo la spunta a Generate sample content. Creiamo quindi un file per la libreria (lib/carte.dart), un file per i test (test/test.dart) e il file di configurazione pubspec.yaml con questa struttura:

├── lib
│   └── carte.dart
├── pubspec.yaml
└── test
    └── test.dart

Apriamo pubspec.yaml, diamo un nome qualsiasi al nostro progetto e aggiungiamo la dipendenza unittest. Al salvataggio del file sarà avviato automaticamente pub che scaricherà in background le dipendenze necessarie.

Apriamo carte.dart e scriviamo la nostra libreria:

library carte;

class Carta{

  int v,s;

  List<String> nomiSemi = ['Picche','Fiori','Quadri','Cuori'];
  List<String> nomiValori = ['Nessuno','Nessuno', '2', '3', '4', '5', '6', '7','8', '9', '10', 'Fante', 'Regina', 'Re','Asso'];

  Carta(this.s,this.v) {
    if ( this.v < 2){
      throw "Il valore non può essere inferiore a 2.";
    }
  }

  String nomeCarta(){
    return '${nomiValori[this.v]} di ${nomiSemi[this.s]}';
  }

  String toString() => this.nomeCarta();

  operator >(Carta altra) {
    if ( this.v > altra.v){
    return true;
  }
  else if (this.v == altra.v){
    if ( this.s > altra.s){
      return true;
      }
    }
  return false;
  }

  operator <(Carta altra) {
    if ( this.v < altra.v){
    return true;
  }
  else if (this.v == altra.v){
    if ( this.s < altra.s){
      return true;
      }
    }
  return false;
  }

  operator ==(Carta altra) {
    if (this.v == altra.v && this.s == altra.s) return true;
    return false;
  }
}

Il formato della carta è semplice: il primo valore passato a Carta() è il seme, il secondo è il valore. Nota: per comodità poniamo l’asso dopo il re, mappandolo 14 così da agevolare le operazioni di comparazione fra le carte (nel gioco del poker l’asso batte il re).

Scriviamo ora dei test per verificare che quanto abbiamo sviluppato precedentemente funzioni:

import 'package:unittest/unittest.dart';
import 'package:droneio_test/carte.dart';

main(){

  // 5 di Fiori
  Carta a = new Carta(1,5);
  // 5 di Picche
  Carta b = new Carta(0,5);
  // Asso di Cuori
  Carta c = new Carta(3,14);
  // Asso di Cuori
  Carta d = new Carta(3,14);

  test('Valori dell carte',(){
    expect(true,a>b);
    expect(false,b>c);
    expect(true,c==d);
  });

  test('Nomi delle carte',(){
    expect('Asso di Cuori', equals(c.nomeCarta()));
  });

}

Importiamo innanzitutto le librerie necessarie: carte.dart e unittest; quest’ultima contiene le funzioni text() e expect(). In questo programma abbiamo 2 test: il primo, “Valori delle carte”, verificherà che una certa carta sia effettivamente minore, maggiore o uguale ad un’altra, e il secondo test verificherà che il metodo nomeCarta() restituisca il nome atteso.

Avviamo test.dart e leggiamo l’output:

unittest-suite-wait-for-done
PASS: Valori dell carte
PASS: Nomi delle carte

All 2 tests passed.
unittest-suite-success

I 2 test sono stati superati con successo quindi possiamo passare alle fasi successive, ovvero il caricamento su repository remota (per questo esempio è stato utilizzato GitHub) e l’importazione in Drone.io.

È buona norma impedire che su github vengano caricati i collegamenti simbolici e il file pubspec.lock creati da pub, quindi creiamo e modifichiamo il file .gitignore come segue:

packages
pubspec.lock
test/packages

Ora che il nostro progetto è su GitHub possiamo procedere con l’importazione in Drone.io: registriamoci su https://drone.io/signup utilizzando il provider “github”, clicchiamo su New Project -> Github e selezioniamo la nostra repository e scegliamo Dart come ambiente di sviluppo.

Per eseguire i test sarà necessario impostare Build Script in questo modo:

pub install
dart test/test.dart

Clicchiamo su Build now e se tutto è andato a buon fine dovremmo visualizzare un output in questa forma:

Screenshot

$ git clone git://github.com/Engeene/dart_droneio_test.git /home/ubuntu/src/github.com/Engeene/dart_droneio_test
Cloning into '/home/ubuntu/src/github.com/Engeene/dart_droneio_test'...
$ dart --version
Dart VM version: 0.3.7.6_r18717 (Tue Feb 19 15:41:33 2013)
$ cat $DART_SDK/revision
18717
$ pub install
Resolving dependencies...
Downloading unittest 0.3.7+6...
Downloading meta 0.3.7+6...
Dependencies installed!
$ dart test/test.dart
unittest-suite-wait-for-done
PASS: Valori dell carte
PASS: Nomi delle carte

All 2 tests passed.
unittest-suite-success

Se modificassimo test/test.dart in modo tale da ottenere un errore avremmo questo output:

Screenshot

unittest-suite-wait-for-done
PASS: Valori dell carte
FAIL: Nomi delle carte
  Expected: 'Asso di Cuori'
       but: was 'Asso di Fiori'.

1 PASSED, 1 FAILED, 0 ERRORS
Unhandled exception:
Exception: Some tests failed.

Ricordiamo che ogni volta che verrà effettuato un commit alla repository su GitHub, Drone.io eseguirà automaticamente i test, il che risulta particolarmente utile per avere sott’occhio lo stato del proprio progetto e gli eventuali bug nelle revisioni:

Screenshot

Come sempre, il codice di esempio utilizzato in questo articolo è disponibile su GitHub.

Leave a Reply

Claudio d'Angelis Articolo scritto da

Programmatore e studente di Informatica, appassionato di musica, web e sistemi UNIX. Collabora con Googlab dall'Ottobre 2012.

Contatta l'autore

Previous post:

Next post: