Heroes / Guida / capitolo 13

Test e buchi

Scrivere test nel sorgente e usare ??? per completare il codice.

Un test verifica il codice nello stesso file. Con ??? puoi lasciare un’espressione incompleta e chiedere al compilatore quale tipo si aspetta. Entrambe le forme fanno parte del linguaggio.

test è una dichiarazione

test "the part that exists, works"
    lunch = [Entry(name: "soup", calories: 120), Entry(name: "bread", calories: 250)]
    assert total_calories(lunch) == 370
examples/gallery/09-holes.hero, righe 30–32

Un test ha una descrizione tra virgolette e un corpo indentato. Puoi scriverlo nello stesso file del codice da verificare. Le compilazioni ordinarie lo escludono dall’eseguibile; non servono librerie aggiuntive, cartelle separate o nomi di file particolari.

assert richiede un bool. Se il controllo fallisce, mostra l’espressione. Nei confronti mostra anche i due valori quando sono stampabili, per esempio numeri, stringhe o booleani:

$ heroes test points.hero
assert failed: dist2(a: Point(x: 0, y: 0), b: Point(x: 3, y: 4)) == 24
  left:  25
  right: 24
FAIL "the 3-4-5 triangle"
ok   "a rectangle keeps its size when it moves"
2 tests, 1 failed

Gli altri test vengono eseguiti e mostrano i risultati. Il codice di uscita è diverso da zero, così uno script può rilevare il fallimento senza analizzare il testo dei messaggi.

??? è un’espressione legale

Scrivi ??? dove manca un valore. Il compilatore verifica il codice circostante e indica il tipo necessario per completare l’espressione.

# Written, tested, done.
function total_calories(entries: [Entry]) -> i64
    total: i64 @= 0

    for e in entries
        total @ total + e.calories

    return total
examples/gallery/09-holes.hero, righe 12–19
# Next up: the compiler will name the expected type and list `entries`,
# `total_calories` and the fields of `Entry` when it reaches this.
function heaviest(entries: [Entry]) -> Entry
    ???
examples/gallery/09-holes.hero, righe 21–24
# The hole can be one argument of an otherwise finished line.
function summary_of(entries: [Entry]) -> str
    return "total " + total_calories(entries).to_str() + ", heaviest " + ???
examples/gallery/09-holes.hero, righe 26–28

Controlla quel file e il compilatore risponde:

$ heroes check holes.hero
hole at holes.hero:24:5
  position: statement — any type, or none
  this function returns: Entry
  in scope:
    entries: [Entry]
hole at holes.hero:28:74
  expected type: str
  in scope:
    entries: [Entry]
  functions that return it:
    summary_of(entries: [Entry])
      # The hole can be one argument of an otherwise finished line.

Nel secondo messaggio il compilatore indica che serve uno str. Elenca poi i nomi disponibili e le funzioni che restituiscono quel tipo, insieme alla prima riga dei rispettivi commenti. Queste informazioni aiutano a scegliere come completare il codice.

Tutto il resto viene controllato lo stesso

Un file con espressioni incomplete viene controllato per intero. Il controllo restituisce il codice 0 solo se non ci sono altri errori. Finché resta un ???, il compilatore non produce un eseguibile e indica il punto da completare:

$ heroes test holes.hero
no binary: 2 holes in holes.hero
hole at holes.hero:24:5
  position: statement — any type, or none
  this function returns: Entry
  in scope:
    entries: [Entry]
hole at holes.hero:28:74
  expected type: str
  in scope:
    entries: [Entry]
  functions that return it:
    summary_of(entries: [Entry])
      # The hole can be one argument of an otherwise finished line.

Il compilatore può quindi controllare un programma scritto a metà senza scambiarlo per uno finito. Un buco non può finire in un eseguibile.

Perché sta nel linguaggio e non dentro un editor

Una persona o un modello può ottenere queste informazioni direttamente dal compilatore, senza installare un editor o estensioni. I tre caratteri ??? indicano nel sorgente il punto ancora da completare.

function main()
    print(summary_of([Entry(name: "tea", calories: 2)]))
examples/gallery/09-holes.hero, righe 34–35

Completa le due espressioni per poter eseguire main. Nel frattempo il compilatore può già controllare il resto del file.

Poi: Il confine con il C, da dove arriva tutto quello che il linguaggio non ha. Torna all’elenco dei capitoli. ← Prima: I moduli e i file

Esegui un programma tuo: bastano quattro comandi. Oppure prendi tutto il linguaggio in un file solo, e tutti i programmi già scritti.