JavaScript é uma linguagem do tipo dinâmico, que oferece forte capacidade de desempenho, mas também torna o compilador quase impossível de fornecer qualquer ajuda aos desenvolvedores. Por esse motivo, sentimos que escrever qualquer código JavaScript deve ter um conjunto poderoso e completo de testes. A Angular possui muitos recursos que facilitam o teste de nossos aplicativos. Não devemos ter desculpa para não escrever testes (é isso ...).
1. Trata -se de não misturar preocupações (trata -se de evitar que o relacionamento do código se torne complicado ...)
O teste de unidade, como nome, é sobre testar uma única "unidade". Os testes de unidade se esforçam para responder a estas perguntas: Já estou correto em minhas considerações lógicas? Os resultados são obtidos pelo método de classificação corretos? Para responder a essas perguntas, é particularmente importante separá -las. Isso ocorre porque, quando estamos testando o método de classificação, não queremos nos preocupar com outros fragmentos relacionados, como elementos DOM ou iniciar solicitações XHR para obter dados, etc. Obviamente, geralmente é difícil chamar uma função separadamente em um projeto típico. A razão para esse problema é que os desenvolvedores geralmente tornam os relacionamentos complicados e acabam fazendo com que um trecho pareça que possa fazer tudo. Ele obtém os dados através do XHR, classifica os dados e depois manipula o DOM. Juntamente com o Angular, podemos escrever um código melhor com mais facilidade, portanto, o Angular nos fornece injeção de dependência de XHR (que podemos simular) e o Angular também cria abstrações que nos permitem classificar o modelo sem precisar manipular o DOM. Portanto, no final, podemos simplesmente escrever um método de classificação e, em seguida, criar um conjunto de dados através do caso de teste para o método de classificação a ser usado ao testar e, em seguida, determinar se o modelo de resultado atende às expectativas. O teste não requer espera que o XHR crie o DOM correspondente e determine se a função opera o DOM corretamente. A idéia principal de Angular inclui a testabilidade do código, mas também exige que façamos a coisa certa. A Angular está comprometida em simplificar o caminho para fazer a coisa certa, mas o Angular não é mágico, o que significa que podemos acabar com uma aplicação inestável se não seguirmos os seguintes pontos.
1. Injeção de dependência
Existem muitas maneiras de obter os recursos de dependência: 1) podemos usar o novo operador; 2) usamos um método bem conhecido chamado "Global Singleton"; 3) Podemos solicitá -lo do Serviço de Registro (mas como obtemos um registro? Você pode verificar os seguintes capítulos); 4) Podemos esperar que seja aprovado.
Dos métodos listados acima, apenas o último é testável, vamos ver o porquê:
1) Usando o novo operador
Basicamente, não há erros ao usar o novo operador, mas o problema é que chamar o construtor por meio de novo vinculará permanentemente o chamador ao tipo. Por exemplo, tentamos instanciar um objeto XHR para que possamos obter alguns dados do servidor.
function myclass () {this.dowork = function () {var xhr = new xrh (); XHR.OPEN (Método, URL, True); xhr.onreadyStateChange = function () {…}; xhr.send (); }}O problema é que, ao testar, geralmente precisamos instanciar um XHR virtual que possa retornar dados de teste ou erros de rede. Ao ligar para o novo XHR (), ligamos permanentemente o XHR real e não há uma boa maneira de substituí -lo. Obviamente, há um remédio ruim e há muitas razões para provar que é uma má ideia:
var Oldxhr = xhr; xhr = new Mockxhr () {}; myclass.dowork (); // julga se o Mockxhr chama xhr = oldxhr através de parâmetros normais; // se você esquecer esta etapa, é fácil causar coisas tristes.2) pesquisa global
Outra maneira de resolver o problema é obter os recursos de dependência em um lugar bem conhecido.
function myclass () {this.dowork = function () {global.xhr ({…}); };}Sem criar uma instância de um novo objeto dependente, o problema é basicamente o mesmo que novo e não há uma boa maneira de interceptar as chamadas globais.xhr ao testar. O problema mais básico do teste é que as variáveis globais precisam ser alteradas para chamar métodos virtuais e são modificados. Para saber mais sobre suas desvantagens, visite aqui: http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/
O código acima é difícil de testar, por isso devemos modificar o estado global:
var Oldxhr = global.xhr; global.xhr = function mockxhr () {…}; var myclass = new myclass (); // julga se o Mockxhr chama de global.xhr = oldxhr através de parâmetros normais; // se você esquecer essa etapa, é fácil causar coisas tristes.3) Registro de serviços
Ter um registro com todos os serviços parece resolver o problema e substituir o serviço necessário no código de teste.
function myclass () {var serviceregistry = ???; this.dowork = function () {var xhr = serviceregistry.get ("xhr"); …};}Mas de onde vem o Serviceregistry? Se for: * recém-formado, o teste não tem chance de redefinir os serviços para testar * a pesquisa global, então o serviço retornado também é global (mas a redefinição é mais fácil, já que há apenas uma variável global a ser redefinida) (o texto por trás é o mesmo que grudado ... eu não entendi)
De acordo com este método, modifique a classe acima para o seguinte método:
var OldServicelocator = Global.Servicelocator; Global.Servicelocator.Set ('xhr', function mockxhr () {}); var myclass = new myclass (); myclass.dowork (); // julga se zombarxhr chama Global.Servicelocator = OldServicelCator; // Se você esquecer esta etapa, é fácil causar coisas tristes.4) Passando em dependências
Finalmente, os recursos de dependência podem ser aprovados.
function myclass (xhr) {this.dowork = function () {xhr ({…}); };}Esse é o método preferido, porque o código não precisa prestar atenção de onde o XHR vem, nem se importa quem criou o XHR. Portanto, o criador da classe pode ser codificado separadamente do consumidor de classe, que separa a responsabilidade da criação da lógica, que é uma visão geral da injeção de dependência.
Esta aula é fácil de testar, e podemos escrever assim no teste:
função xhrmock (args) {…} var myclass = new myclass (xhrmock); myclass.dowrok (); // faça alguns julgamentos ... através desse código de teste, podemos perceber que nenhuma variável global está corrompida.Dependência-injeção (//www.vevb.com/article/91775.htm) incluída no Código Angular, escrito dessa maneira, facilita a gravação do código de teste. Se quisermos escrever um código altamente testável, é melhor usá -lo.
2 controladores
A lógica torna cada aplicativo único, e é isso que queremos testar. Se nossa lógica for misturada com operações DOM, será tão difícil testar como o exemplo a seguir:
function wastwrondcontroller () {// Obtenha uma referência ao objeto DOM var msg = $ ('. Ex1 span'); var input = $ ('. Ex1 entrada'); força de var; this.Grade = function () {msg.RemoveClass (força); var pwd = input.val (); senha.Text (PWD); if (pwd.length> 8) {fortale = 'strong'; } else if (pwd.length> 3) {forcent = 'Medium'; } else {forcent = 'fracy'; } msg.addclass (força) .text (força); }}O código acima encontrará problemas ao testar, pois exige que tenhamos o DOM correto ao executar o teste. O código de teste será o seguinte:
var input = $ ('<input type = "text"/>'); var span = $ ('<span>'); $ ('corpo'). html ('<div>'). find ('div'). append (entrada) .append (span); var pc = novo PasswordController (); input.Val ('ABC'); pc.grade (); espera (span.Text ()). ToEqual ('fraco'); $ ('corpo'). Html ('');No Angular, o controlador separa estritamente a lógica de operação DOM, que reduzirá bastante a dificuldade de escrever casos de teste. Dê uma olhada no exemplo a seguir:
function wastwrcntrl ($ scope) {$ scope.password = ''; $ scope.Grade = function () {var size = $ scope.password.length; if (tamanho> 8) {$ scope.strength = 'Strong'; } else if (tamanho> 3) {$ scope.strength = 'Medium'; } else {$ scope.Strength = 'fracy'; }};}O código de teste é direto:
var PC = novo PasswordController ($ SCOPE); PC.Password ('ABC'); PC.GRADE (); espera ($ SCOPE.STRENÇÃO) .TOEQUAL ('fraco');Vale ressaltar que o código de teste não é apenas mais descontínuo, mas é mais fácil de rastrear. Sempre dissemos que os casos de teste estão contando histórias, não julgando outras coisas irrelevantes.
3. Filtros
O filtro (http://docs.angularjs.org/api/ng.$filter) é usado para converter dados em um formato amigável. Eles são importantes porque separam a responsabilidade de converter formatos da lógica do aplicativo, simplificando ainda mais a lógica do aplicativo.
mymodule.filter ('comprimento', function () {return function (text) {return (''+(text || '')). length;}}); var comprimento = $ filtro ('length'); espera (comprimento (nulo).4. Diretivas
5. Mocks
6. Isolamento do Estado Global
7. maneira preferida de teste
8. JavaScriptTestdriver
9. Jasmim
10. Projeto de amostra
Continuaremos atualizando artigos relacionados no futuro. Obrigado pelo seu apoio a este site!