Padrões de teste de componentes FlexUnit:usar addAsync ou inicializar manualmente?
-
09-06-2019 - |
Pergunta
Estamos usando o Flex há cerca de 6 meses aqui no trabalho e descobri que meus primeiros lotes de testes do FlexUnit envolvendo componentes personalizados tenderiam a seguir este tipo de padrão:
import mx.core.Application;
import mx.events.FlexEvent;
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
private var component:CustomComponent;
public function testSomeAspect() : void {
component = new CustomComponent();
// set some properties...
component.addEventListener(FlexEvent.CREATION_COMPLETE,
addAsync(verifySomeAspect, 5000));
component.height = 0;
component.width = 0;
Application.application.addChild(component);
}
public function verifySomeAspect(event:FlexEvent) : void {
// Assert some things about component...
}
override public function tearDown() : void {
try {
if (component) {
Application.application.removeChild(component);
component = null;
}
} catch (e:Error) {
// ok to ignore
}
}
Basicamente, você precisa ter certeza de que o componente foi totalmente inicializado antes de poder verificar com segurança qualquer coisa sobre ele, e no Flex isso acontece de forma assíncrona após ele ter sido adicionado à lista de exibição.Então você precisa configurar um retorno de chamada (usando a função addAsync do FlexUnit) para ser notificado quando isso acontecer.
Ultimamente tenho chamado manualmente os métodos que o tempo de execução chamaria para você nos locais necessários, então agora meus testes tendem a ser mais parecidos com isto:
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
public function testSomeAspect() : void {
var component:CustomComponent = new CustomComponent();
component.initialize();
// set some properties...
component.validateProperties();
// Assert some things about component...
}
Isso é muito mais fácil de seguir, mas parece que estou trapaceando de qualquer maneira.O primeiro caso é colocá-lo no aplicativo atual (que seria o aplicativo shell do executor de teste de unidade), e o último não é um ambiente "real".
Eu queria saber como outras pessoas lidariam com esse tipo de situação?
Solução
Não vejo nada de errado em usar a versão assíncrona.Posso concordar que a segunda versão é mais curta, mas não tenho certeza se acho que seja mais fácil de seguir.O teste faz muitas coisas que você normalmente não faria, enquanto o primeiro exemplo é mais fiel ao modo como você usaria o componente fora do ambiente de teste.
Além disso, na segunda forma, você deve ter certeza de fazer exatamente o que o framework faria, perder uma etapa e seu teste não ser relevante, e cada teste deve repetir esse código.Parece-me que é melhor testá-lo em uma situação o mais próxima possível da realidade.
Você poderia dar uma olhada dpUintde sequências, eles tornaram os testes de componentes um pouco mais declarativos:
public function testLogin():void {
var passThroughData:Object = new Object();
passThroughData.username = "myuser1";
passThroughData.password = "somepsswd";
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceSetter(form.usernameTI, {text:passThroughData.username}));
sequence.addStep(new SequenceWaiter(form.usernameTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceSetter(form.passwordTI, {text:passThroughData.password}));
sequence.addStep(new SequenceWaiter(form.passwordTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceEventDispatcher(form.loginBtn, new MouseEvent("click", true, false)));
sequence.addStep(new SequenceWaiter(form, "loginRequested", 100));
sequence.addAssertHandler(handleLoginEvent, passThroughData);
sequence.run();
}
(exemplo do dpUint wiki, Veja aqui para mais informações).