sinais, passo 1: iniciando o TDD

Vamos usar TDD para desenvolver esse projeto. A primeira coisa então é escrever um teste, no arquivo-fonte runefinder_test.go. Nosso primeiro teste verifica a função AnalisarLinha, que deve extrair um caractere e um nome de uma linha do UnicodeData.txt:

package main // ➊

import "testing" // ➋

const linhaLetraA = `0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061;` // ➌

func TestAnalisarLinha(t *testing.T) { // ➍
	runa, _ := AnalisarLinha(linhaLetraA) // ➎
	if runa != 'A' {                      // ➏
		t.Errorf("Esperava 'A', veio %c", runa) // ➐
	}
}

Vejamos o que temos aqui:

➊ Todo arquivo-fonte em Go precisa declarar o pacote ao qual ele pertence. Para programas executáveis, o pacote deve ser main. Bibliotecas devem usar um nome igual à última parte do caminho até seu código-fonte, ex. sinais.

➋ Importamos o pacote testing da biblioteca padrão.

➌ Definimos uma constante do tipo string (não é preciso declarar o tipo, porque o compilador identifica que o valor à direita do = é uma string).

➍ Todas as funções de teste precisam começar com o prefixo Test, e recebem como argumento um ponteiro para um objeto testing.T, através do qual acessamos métodos como t.Errorf neste exemplo. As declarações em Go tem a forma x tipo, onde x é o identificador sendo declarado, seguido de seu tipo (como em Pascal!)

➎ Nossa primeira função devolverá dois valores: um caractere e uma string — que por enquanto vamos ignorar (mais detalhes sobre essa linha a seguir).

➏ Note a ausência de parênteses ao redor da condição, e o uso de aspas simples para indicar que 'A' é um caractere e não uma string.

➐ Um dos métodos para reportar erros em testes é t.Errorf. Em Go, funções que terminam com a letra f normalmente aceitam strings com códigos de formatação, semelhante à função printf em C.

A linha ➎ traz algumas peculiaridades da linguagem Go:

Rodando o teste

Após criar o arquivo runefinder_test.go, você pode usar o comando go test para executar o teste. O resultado será este:

$ go test
# github.com/ThoughtWorksInc/sinais
./runefinder_test.go:8: undefined: AnalisarLinha
FAIL	github.com/ThoughtWorksInc/sinais [build failed]

Obviamente, falta definir a função AnalisarLinha em algum lugar. Vamos lá.

Primeira função: AnalisarLinha

Vamos criar outro arquivo-fonte, com nome runefinder.go. O mínimo que precisamos para fazer passar o teste é isso:

package main // ➊

func AnalisarLinha(ucdLine string) (rune, string) { // ➋
	return 'A', "LETRA A" // ➌
}

Vejamos o que temos em runefinder.go:

➊ Novamente declaramos o mesmo pacote, assim os identificadores deste arquivo ficam acessíveis para outros arquivos do mesmo pacote.

➋ Esta função é pública porque seu nome começa com uma letra maiúscula. Isso não é apenas uma convenção, é algo que o compilador verifica. Esta linha também declara que a função recebe um argumento do tipo string e devolve um par de resultados, respectivamente rune e string.

➌ Apenas para fazer passar o teste, devolvemos uma rune e uma string.

Feito isso, rodamos o teste:

$ go test
PASS
ok  	github.com/ThoughtWorksInc/sinais	0.013s

Sucesso!

OK, completamos nosso primeiro baby step: fizemos a função mais simples possível que faz o teste passar. A função AnalisarLinha ignora totalmente o argumento passado, e o teste confere a runa mas ignora a string devolvida. Mas um teste passando é um bom começo!

Hora de ler o Passo 2, código no diretório sinais02.