Depois de alterar ou adicionar o código, execute testes de unidade existentes e considere escrever mais. Todos os testes são executados nas versões descomprimidas do código.
Há dois conjuntos de testes de unidade: testes de JS e testes de gerador de blocos.
Testes JS
Os testes de JS confirmam a operação de funções JavaScript internas no núcleo do Blockly. Usamos o Mocha para executar testes de unidade, o Sinon para simular dependências e o Chai para fazer declarações sobre o código.
Como executar testes
Nas amostras em bloco e em bloco, npm run test
executará os testes de unidade. Em
com bloqueio, isso também executará outros testes, como inspeção e compilação. Você pode
Também abra tests/mocha/index.html
em um navegador para executar todos os modelos mocha de forma interativa
provas.
Testes de escrita
Usamos a interface Mocha TDD para executar testes. Os testes são organizados em conjuntos,
que pode conter mais subpacotes e/ou testes. Geralmente, cada
componente do Blockly (como toolbox
ou workspace
) tem um arquivo de teste
com uma ou mais suítes. Cada suíte pode ter setup
e teardown
que será chamado antes e depois, respectivamente, de cada teste da
Google Workspace.
Ajudantes de teste
Temos várias funções auxiliares específicas do Blockly que podem ser úteis a escrever testes. Estes podem ser encontrados em núcleo e em blockly-samples.
As funções auxiliares incluem sharedTestSetup
e sharedTestTeardown
, que
são obrigatórios e precisam ser chamados antes e depois dos testes (consulte a seção
"Requisitos").
sharedTestSetup
:
- Configura timers falsos de sinon (em alguns testes, você precisará usar
this.clock.runAll
). - O stub Blockly.Events.fire é acionado imediatamente (configurável).
- Configura a limpeza automática de blockTypes definidos por
defineBlocksWithJsonArray
. - Declara algumas propriedades no contexto
this
que devem ser acessíveis:this.clock
(mas não deve ser restaurado, caso contrário causará problemas nosharedTestTeardown
)this.eventsFireStub
this.sharedCleanup
(para ser usado comaddMessageToCleanup
eaddBlockTypeToCleanup
) (OBSERVAÇÃO: não é necessário usaraddBlockTypeToCleanup
se você definiu o bloco usandodefineBlocksWithJsonArray
)
A função tem um parâmetro options
opcional para definir a configuração. No momento,
ele é usado apenas para determinar se o stub Blockly.Events.fire
será acionado
imediatamente (será criado por padrão).
sharedTestTeardown
:
- Descarta o espaço de trabalho
this.workspace
(dependendo de onde foi definido, consulte a seção Requisitos de teste para mais informações). - Restaura todos os stubs.
- Limpa todos os tipos de bloco adicionados por
defineBlocksWithJsonArray
eaddBlockTypeToCleanup
. - Limpa todas as mensagens adicionadas usando
addMessageToCleanup
.
Requisitos de teste
- Cada teste precisa chamar
sharedTestSetup.call(this);
como a primeira linha da configuração do pacote mais externo esharedTestTeardown.call(this);
como o última linha na eliminação do pacote mais externo de um arquivo. - Se você precisar de um espaço de trabalho com uma caixa de ferramentas genérica, use um dos
caixas de ferramentas predefinidas
no teste
index.html
. Veja abaixo um exemplo. - Descarte corretamente o
this.workspace
. Na maioria dos testes, você definirthis.workspace
no pacote mais externo e usá-lo para todas as mas, em alguns casos, é possível defini-los ou redefini-los em um conjunto interno Por exemplo, um dos testes exige um espaço de trabalho com opções diferentes do que o configurado originalmente). Ele precisa ser descartado no final do teste.- Se você definir
this.workspace
no pacote mais externo e nunca o redefinir, não será necessário fazer mais nada. Ele será descartado automaticamente porsharedTestTeardown
. - Se você definir
this.workspace
pela primeira vez em um pacote interno (ou seja, se você não o tiver definido no pacote mais externo), será necessário descartá-lo manualmente chamandoworkspaceTeardown.call(this, this.workspace)
no descarte desse pacote. - Se você definir
this.workpace
no pacote mais externo, mas redefinir em um pacote de testes interno, primeiro chameworkspaceTeardown.call(this, this.workspace)
antes de redefini-la para eliminar o espaço de trabalho original definido no pacote de nível superior. Você também precisa descartar manualmente o novo valor chamandoworkspaceTeardown.call(this, this.workspace)
novamente na eliminação de essa suíte interna.
- Se você definir
Estrutura de teste
Os testes de unidade geralmente seguem uma estrutura definida, que pode ser resumida como organizar, agir, afirmar.
- Organizar: configurar o estado do mundo e todas as condições necessárias para o comportamento em teste.
- Ação: chame o código em teste para acionar o comportamento que está sendo testado.
- Assert: faça declarações sobre o valor de retorno ou as interações com objetos simulados para verificar a exatidão.
Em um teste simples, pode não haver nenhum comportamento para organizar, e os ato e é possível combinar as etapas de declaração colocando a chamada em linha para o código em teste na declaração. Para casos mais complexos, seus testes serão mais legíveis se você seguir essas três etapas.
Confira um exemplo de arquivo de teste (simplificado).
suite('Flyout', function() {
setup(function() {
sharedTestSetup.call(this);
this.toolboxXml = document.getElementById('toolbox-simple');
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: this.toolboxXml
});
});
teardown(function() {
sharedTestTeardown.call(this);
});
suite('simple flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
});
test('y is always 0', function() {
// Act and assert stages combined for simple test case
chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout is 0');
});
test('x is right of workspace if flyout at right', function() {
// Arrange
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
viewWidth: 100,
});
this.flyout.targetWorkspace.toolboxPosition = Blockly.TOOLBOX_AT_RIGHT;
this.flyout.toolboxPosition_ = Blockly.TOOLBOX_AT_RIGHT;
// Act
var x = this.flyout.getX();
// Assert
chai.assert.equal(x, 100, 'x is right of workspace');
});
});
});
Observações sobre este exemplo:
- Uma suíte pode conter outras suítes com métodos
setup
eteardown
adicionais. - Cada conjunto e teste tem um nome descritivo.
- As declarações de Chai são usadas para fazer declarações sobre o código.
- Você pode fornecer um argumento de string opcional que será exibido se o teste falhar. Isso facilita a depuração de testes corrompidos.
- A ordem dos parâmetros é
chai.assert.equal(actualValue, expectedValue, optionalMessage)
. Se você trocaractual
eexpected
, as mensagens de erro não farão sentido.
- O Sinon é usado para criar métodos stub quando você não quer chamar o código real. Neste
exemplo, não queremos chamar a função de métricas reais porque ela
não é relevante para este teste. Só nos preocupamos com o modo como os resultados são usados pelo
o método em teste. O Sinon cria um stub da função
getMetrics
para retornar uma que podem ser facilmente verificadas nas nossas declarações de teste. - Os métodos
setup
para cada pacote precisam conter apenas a configuração genérica que se aplica a todos os testes. Se um teste para um comportamento específico depender de uma determinada condição, essa condição precisa ser claramente indicada no teste relevante.
Testes de depuração
- É possível abrir os testes em um navegador e usar as ferramentas para desenvolvedores para definir pontos de interrupção e investigar se os testes estão falhando ou passando de forma inesperada.
Defina
.only()
ou.skip()
em um teste ou pacote para executar apenas esse conjunto de testes ou pular um teste. Exemplo:suite.only('Workspace', function () { suite('updateToolbox', function () { test('test name', function () { // ... }); test.skip('test I don’t care about', function () { // ... }); }); });
Lembre-se de removê-los antes de confirmar seu código.
Testes do gerador de blocos
Cada bloco tem seus próprios testes de unidade. Esses testes verificam se os blocos geram do que as funções pretendidas.
- Carregue
tests/generators/index.html
no Firefox ou Safari. O Chrome e o Opera têm restrições de segurança que impedem o carregamento dos testes do sistema local "file://" (problemas 41024 e 47416). - Escolha a parte relevante do sistema para testar no menu suspenso e clique em "Carregar". Os blocos vão aparecer no espaço de trabalho.
- Clique em "JavaScript".
Copie e execute o código gerado em um console JavaScript. Se a saída terminar com "OK", o teste foi aprovado. - Clique em "Python".
Copie e execute o código gerado em um interpretador do Python. Se a saída terminar com "OK", o teste foi aprovado. - Clique em "PHP".
Copie e execute o código gerado em um interpretador do PHP. Se a saída terminar com "OK", o teste foi aprovado. - Clique em "Lua".
Copie e execute o código gerado em um intérprete Lua. Se a saída terminar com "OK", o teste foi aprovado. - Clique em "Dart".
Copie e execute o código gerado em um interpretador do Dart (link em inglês). Se a saída terminar com "OK", o teste foi aprovado.
Como editar testes de gerador de blocos
- Carregue
tests/generators/index.html
em um navegador. - Escolha a parte relevante do sistema no menu suspenso e clique em "Carregar". Os blocos vão aparecer no espaço de trabalho.
- Faça alterações ou adições nos blocos.
- Clique em "XML".
- Copie o XML gerado para o arquivo apropriado em
tests/generators/
.