O item de teste do Visual Studio 2010 CodedUITest é utilizado quando há a necessidade de simular a interação do usuário com um sistema. Será proposto uma forma de trabalhar quando a regra é verificar um componente e não uma informação no mapeamento da interação.
O exemplo se trata do seguinte caso de teste:
Requisito de Teste:
A aplicação é uma parte de uma tela completa onde será testado apenas o componente ListBox que exibe os últimos 10 cadastros.
O teste deve garantir que a primeira linha do ListBox foi o ultimo item a ser cadastrado no sistema.
Pré requisito do teste:
Abrir a aplicação.
Passos do teste:
1- Clicar no botão “Tela”.
2- Selecionar o ultimo cadastro que está no banco de dados.
3- Verificar se o que está na primeira linha do ListBox é o ultimo registro que foi cadastrado no banco.
Pós requisito do teste:
Fechar aplicação.
Bem vamos ao projeto de teste, para isso crie no VS2010 um projeto de teste.
[Imagem 1:Novo projeto teste]
[Imagem 2: Solution projeto teste]
Adicione um novo item ao projeto, deve ser do tipo CodedUITest.
O Visual Studio irá perguntar se deseja mapear o caminho a ser traçado pelo programa ou irá utilizar um já existente. Selecione a opção para criar um mapeamento.
[Imagem3: Gerar código de teste UI]
O aplicativo que abre é o Coded UI Builder, nele será gravado os passos executados pelo usuário e transforma em código e carrega uma classe do caminho mapeado e seus objetos.
[Imagem4: Coded UI Builder]
Vamos abrir a aplicação e gravar os passos do caso de teste (nesse exemplo é apenas um botão, mas, poderíamos ter um menu ou qualquer outro formulário)
- Clicar em Record, a partir disso será gravado as interações com o sistema
[Imagem5: Start record]
Cada interação é importante gerar o código para definir o que é cada passo.
Após executar uma etapa verificamos os passos mapeados (etapa opcional) e geramos o código, irá criar um método.
[Imagem6: Passos gravados]
[Imagem7: Criar método]
Após alguns passos executados no caso de teste está uma validação, o “Assert” realizado pelo Codo UI Builder irá definir uma propriedade de um objeto na tela que vai ser comparada.
[Imagem8: Identificando validação]
Como em nosso exemplo temos um ListBox e devo garantir que ID exibido será o ultimo ID do banco vou usar um Assert na propriedade “Name” do componente ListBoxItem. Para isso segue e arraste “o alvo” do Coded UI Builder até o componente que deseja verificar, depois, coloque a verificação em uma propriedade.
[Imagem9: Adicionar verificação]
Use o botão gerar código para criar a verificação na classe de mapeamento.
[Imagem10]
Como o leitor pode perceber até esse ponto realizamos apenas os passos 1 e 3 do caso de teste, para o passo 2 será necessário criar uma classe que vai acessar o banco de dados e trazer qual o ultimo registro que foi gravado para a comparação.
Nesse exemplo vou utilizar Linq to SLQ (poderia ser utilizado entity framework ou qualquer forma de acesso as informações) para criar o método, ficou dessa maneira:
…
public static class AcessaInfo
{
public static string codUltimoRegistro()
{
using (AcessoInfoDataContext context = new AcessoInfoDataContext())
{
System.Data.Linq.Table<LIST> tblList = context.GetTable<LIST>();
return (from reg in tblList
orderby reg.LIS_ID descending
select reg.LIS_ID).FirstOrDefault().ToString();
}
}
}
…
E o método do passo 2 fica assim, dentro da classe CodedUITest:
private void SelecionaUltimoRegistroAtribuiCampo()
{
this.UIMap.VerificaListBoxItemExpectedValues.UIItem211709201143ListItemDisplayText1 = AcessaInfo.codUltimoRegistro();
}
Existem coisas que precisam ser feitas antes de iniciar e ao finalizar o teste e isso fica definido nos métodos que estão com o atributo ‘TestInicialize’ e ‘TestCleanUp’.
Vamos preencher esses métodos com os pré-requisitos e pós-requisitos.
Para abrir e fechar a aplicação será necessário a classe ApplicationUnderTest. Ficando assim:
#region Additional test attributes
// You can use the following additional attributes as you write your tests:
ApplicationUnderTest app = new ApplicationUnderTest();
string caminhoApp = @”C:\Test\app\WinAppListBox.exe”;
////Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
app = ApplicationUnderTest.Launch(caminhoApp);
}
////Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
app.Close();
}
#endregion
Agora o teste pode ser executado, para isso vamos “debugar” para verificar se está conforme o esperado.
[Imagem 11]
Problema:
O teste foi executado com sucesso, mas as validações estão como o codedUIBuilder criou e não é a validação que queremos, se for adicionado um novo registro vai continuar a buscar o registro indicado para o CodedUIBuilder.
O site MSDN.com recomenda (nas boas práticas de CodeUITest) que não altere a classe de mapeamento, mas o que foi criado não é o que o meu teste precisa.
Esse problema eu consegui resolver com o método GetChildren() da classe UIControl. Resgatando todos os “filhos” do componente ListBox e retornando o primeiro que seja ListBoxItem. Também pode servir de solução para outros componentes como GroupBox.
Fui até o método do mapeamento e verifiquei qual classe está sendo buscada, veja o caminho que foi feito pelo CodedUIBuilder:
WinListItem uIItem211709201143ListItem = this.UIJanelaExemploListBoxWindow.UILbxUltimosWindow.UIItem211709201143ListItem;
Na definição da classe do item foi verificado que o critério de pesquisa está fixo no código que vai ser tal ID.
[Imagem 12]
Nessa definição do item que vamos corrigir com o GetChildren()
No meu caso tive que buscar primeiro o WinList e nele buscar pelo primeiro componente WinListItem
public WinListItem UIItem211709201143ListItem
{
get
{
if ((this.mUIItem211709201143ListItem == null))
{
this.mUIItem211709201143ListItem = new WinListItem(this);
#region Search Criteria
//this.mUIItem211709201143ListItem.SearchProperties[WinListItem.PropertyNames.Name] = “21 17/09/2011 43”;
//this.mUIItem211709201143ListItem.WindowTitles.Add(“JanelaExemploListBox”);
#endregion
UITestControlCollection componentes = this.GetChildren();
foreach (UITestControl ui in componentes)
{
if (ui.ControlType.Equals(ControlType.List))
{
UITestControlCollection itensList = ui.GetChildren();
foreach(UITestControl item in itensList)
{
if(item.ControlType.Equals(ControlType.ListItem)
{ return mUIItem211709201143ListItem = (WinListItem)item; }
}
}
}
}
return this.mUIItem211709201143ListItem;
}
}
Não consegui encontrar outra maneira de resolver esse problema e até esse momento está funcionando assim. Aceito sugestões e criticas de como melhorar esse tipo de trabalho.
Conclusão para a definição de um componente é necessário alterar a forma como o mapeamento é feito e atribuir diretamente o componente ao desejado para que as validações da interação seja correta em outras informações passadas.
Código fonte do projeto aqui.
Qualquer dúvida entrar em contato.
Para saber mais:
MSDN Coded UI Test – http://msdn.microsoft.com/en-us/library/dd286726.aspx
Blog MSDN – http://blogs.msdn.com/b/mathew_aniyan/archive/2009/01/20/coded-ui-test.aspx
Comunidade DevBrasil – http://devbrasil.net/group/alm
An impressive share! I have just forwarded this onto a co-worker who had
been doing a little homework on this. And he actually bought me dinner due to the fact that I discovered it for him.
.. lol. So allow me to reword this…. Thanks for the meal!
! But yeah, thanks for spending time to talk
about this topic here on your web page.
You are responsible for making it happen. Do the same for the world. Thank you for the feedback. 😀