 | Nível: Intermediário Gou Nakashima, Yamato Software Development Laboratory (YSL), IBM Japan Masahiro Ohkawa, Yamato Software Development Laboratory (YSL), IBM Japan
16/Jul/2009 O IBM Rational Functional Tester fornece recursos pelos quais
os usuários podem automatizar os testes de seus aplicativos GUI de forma
eficiente. A equipe de Engenharia de Software de Qualidade (QSE) IBM apresentou
uma estrutura hierárquica, conhecida como estrutura QSE, para facilitar
a manutenção. Essa estrutura usa o recurso de reconhecimento de objeto do
Rational Functional Tester. Este artigo mostra como estender a estrutura QSE
e usar os recursos do Rational Functional Tester para melhorar a produtividade
também. Veremos também dicas para testes de aplicativos que suportam de forma eficiente múltiplos idiomas.
Introdução
O IBM® Rational® Functional Tester fornece recursos para automatizar
testes. Para usar o recurso de gravação, grave uma atividade de teste e
salve-a como script de teste. Depois, é possível executar o script de
teste sempre que quiser executar o mesmo teste. Se quiser inserir dados durante o teste,
use o recurso de conjunto de dados de teste durante a gravação. Se for usado o recurso de conjunto
de dados de teste, será possível mudar os dados de entrada antes de executar
o script de testar, sem regravar a atividade de teste. Pode-se usar o
recurso de ponto de verificação, pelo qual o Rational Functional Tester
compara os valores reais com os valores esperados e depois gera um relatório
com informações detalhadas que mostram se você obteve os resultados esperados
ou não. Contudo, uma possível preocupação ao usar o recurso de gravação
é que talvez seja necessário regravar a atividade de teste quando o aplicativo
a ser testado é alterado. Para minimizar seus esforços, a equipe
de Engenharia de Software de Qualidade (QSE) IBM apresentou uma estrutura
hierárquica, conhecida como estrutura QSE. A estrutura QSE isola os
objetos GUI com etapas de teste. O Rational Functional Tester fornece o
recurso Mapa de Objeto de Teste pelo qual podem ser obtidos objetos GUI. Pode-se
executar ações no GUI usando os métodos dos objetos GUI. A estrutura QSE consiste
nas três camadas seguintes.
- A pasta appobjects contém os objetos GUI obtidos pelo recurso
de mapa de objeto de teste.
- A pasta tasks contém programas para executar ações GUI usando
objetos na pasta appobjects. As ações GUI podem ser categorizadas e
implementadas como tarefas. Por exemplo, o processo de login pode ser
implementado como tarefa.
- A pasta testcases contém programas que podem ser usados para executar
casos de teste usando programas na pasta tasks e para registrar os resultados.
É possível usar a estrutura QSE para melhorar a sustentabilidade. Para obter
mais informações sobre a estrutura QSE, consulte o item Estrutura Orientada a Objetos
para o IBM Rational Functional Tester na seção Recursos. Este artigo
mostra como automatizar os testes de forma mais eficiente estendendo a estrutura
QSE e utilizando os recursos do Rational Functional Tester, como conjunto de dados
de teste e pontos de verificação. Este artigo também lhe dá algumas dicas sobre como
testar aplicativos que suportam múltiplos idiomas.
Fornecer o método
de controle de GUI Analise o teste de aplicativo mostrado na Figura 1.
Figura 1. GUI de Aplicativo
Clique para ampliar
Nessa GUI, é possível selecionar os itens de menu Ações > Criar Conjunto, como
mostrado na Figura 2. Esses objetos podem ser obtidos pelo recurso Mapa de Objeto de Teste.
Figura 2. Menus de
aplicativo
Com o arquivo JAR fornecido com a estrutura QSE, é possível definir os
métodos mostrados na Figura 3 e Listagem 1 para obter objetos GUI obtidos pelo recurso Mapa de Objeto de Teste.
Figura 3. Objetos de
teste e programa para obter objetos GUI
Clique para ampliar
Listagem 1. Programa para obter objetos GUI
package appobjects;
import resources.appobjects.MainGUIHelper;
import ibm.widgets.*;
import ibm.widgets.ancestors.*;
import ibm.widgets.swt.*;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;
public class MainGUI extends MainGUIHelper {
public ToggleWidget getActions() {
TestObject to = actions(ANY, NO_STATE);
return new ToggleWidget(to);
}
public ToggleWidget getActionsCreateNewSet() {
TestObject to = actionsCreateNewSet(ANY, NO_STATE);
return new ToggleWidget(to);
}
public ToggleWidget getConfigureGroupDiscoveryOptions() {
TestObject to = configureGroupDiscoveryOptions(ANY, NO_STATE);
return new ToggleWidget(to);
}
public ToggleWidget getCreateNewView() {
TestObject to = createNewView(ANY, NO_STATE);
return new ToggleWidget(to);
}
public SubitemWidget getGrdTree() {
TestObject to = grdTree(ANY, NO_STATE);
return new SubitemWidget(to);
}
public ToggleWidget getRunGroupDiscovery() {
TestObject to = runGroupDiscovery(ANY, NO_STATE);
return new ToggleWidget(to);
}
public ToggleWidget getRunTraceAnalyzer() {
TestObject to = runTraceAnalyzer(ANY, NO_STATE);
return new ToggleWidget(to);
}
// -----------------------------------------
public void testMain (Object[] args)
{
// O teste da unidade pode vir aqui
// (será excluída na próxima vez que o ClasGenerator for executado)
}
} |
O programa na Listagem 2 simula o clique no menu Ações e depois no
submenu Criar Conjunto.
Listagem 2. Exemplo de programa para clicar em um item de menu
MainGUI mainGui = new MainGUI();
mainGui.getActions().click();
mainGui.getActionsCreateNewSet().click(); |
Como
este exemplo mostra, é possível manipular facilmente seu GUI usando objetos
GUI. Contudo, pode ser difícil descobrir que método é usado para executar uma
ação GUI. A Figura 4 mostra um exemplo: pense no caso em que se dá um clique
com o botão direito do mouse no nó da árvore.
Figura 4. Menu
suspenso de um nó de árvore
No caso de uma árvore, não é possível obter cada nó de árvore como objeto.
Como mostrado na Figura 5, é preciso obter o objeto de árvore e usar um dos
métodos para dar um clique com o botão direito do mouse em um nó da árvore.
Figura 5. Captura
de um objeto de árvore
Se você não sabe como uma ação GUI é executada com um objeto GUI (como nesse
exemplo), pode usar o recurso de gravação e então se referir ao programa
gerado. Nesse exemplo, quando damos um clique com o botão direito do mouse
sobre o nó enquanto gravamos, obtemos um programa como o mostrado na Listagem 3.
Listagem 3. Programa gerado para simular o clique com o botão direito do mouse sobre o nó da árvore
public void testMain(Object[] args)
{
// Frame: Database Relationship Analyzer
grdTree().click(RIGHT, atPath("SAMPLE->ORDER->TRACE_ANALYSIS"));
} |
Não é
eficiente gravar esse tipo de programa na pasta tasks sempre que precisar
dele. Em vez disso, é bom gravar um método genérico em uma classe para simular
a ação acima, que herda a classe de objeto GUI na pasta appobjects. Esse tipo
de classe não precisa ser criado como script do Rational Functional Tester:
basta criá-lo como classe ™ Java. Crie uma pasta, como uma
chamada apputils, para guardar esse tipo de classe.
O programa na Listagem 4 mostra um método genérico para dar um clique com o
botão direito do mouse sobre o nó da árvore. A classe MainGUIUtil
herda a classe MainGUI. A classe MainGUI contém
os objetos GUI na janela principal e é colocada sob a pasta appobjects. O método grdTree usado
anteriormente para obter o objeto de árvore foi substituído por aquele definido na classe MainGUI, que é o método getGrdTree nesse exemplo.
Listagem 4. Exemplo de programa para simular clique com o botão direito do mouse sobre o nó da árvore
public class MainGUIUtil extends MainGUI {
public void rightClickView(String dbName, String setName, String viewName) {
String s = dbName + "->" + setName + "->" + viewName;
getGrdTree().click(RIGHT, atPath(s));
} |
Usando métodos como esses, os programas na pasta tasks podem ser implementados
intuitivamente com ações GUI.
Automação eficaz do processamento de
entrada de dados Com a estrutura QSE, as etapas para entrada de dados são
as seguintes.
- Capture cada campo de entrada para obter seu objeto GUI usando o recurso
Mapa de Objeto de Teste.
- Defina métodos para obter os objetos GUI.
- Determine os valores de entrada usando os métodos dos objetos GUI.
É possível executar com eficiência as ações de entrada de dados usando o recurso
Datapool de Teste. Por exemplo, a Figura 6 mostra um GUI com vários campos de entrada.
Considere a entrada de dados nessa GUI.
Figura 6. GUI de aplicativo
com campos de entrada
Após abrir esse GUI, comece a gravar, depois capture essa janela selecionando Inserir
Comandos Acionados por Dados. Após isso, pause a gravação, dê entrada em dados simulados
para ativar o botão OK, continue a gravação, clique em
OK e pare a gravação. Ao fazer isso, é gerado o programa mostrado na Figura 7 e
Listagem 5. Se quiser aplicar essa técnica com um assistente que consiste em múltiplos
painéis, insira um comando acionado por dados em cada painel de modo a parametrizar todos
os campos de entrada.
Figura 7. Programa
gerado com o recurso Datapool de Teste
Clique para ampliar
Listagem 5. Programa gerado
package recordingobjects;
import resources.recordingobjects.RunTraceAnalyzerGUIRecordingHelper;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.object.interfaces.SAP.*;
import com.rational.test.ft.object.interfaces.WPF.*;
import com.rational.test.ft.object.interfaces.dojo.*;
import com.rational.test.ft.object.interfaces.siebel.*;
import com.rational.test.ft.object.interfaces.flex.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;
public class RunTraceAnalyzerGUIRecording extends RunTraceAnalyzerGUIRecordingHelper
{
public void testMain(Object[] args)
{
// Código Orientado por Dados inserido em 28/02/2009
//
schemaName().setText(dpString("SchemaName"));
tableName().setText(dpString("TableName"));
startDate().setText(dpString("StartDate"));
startTime().setText(dpString("StartTime"));
endDate().setText(dpString("EndDate"));
endTime().setText(dpString("EndTime"));
ok().click();
}
} |
Se for definido um método que contenha esse programa, outros programas
poderão invocar o método. Quando se invoca o método, os valores definidos
no datapool de teste são configurados nos campos apropriados. Como se vê
na Figura 7 e Listagem 5, o método dpString é usado
para obter um valor do datapool de teste. Se for alterado o método
de passar valores de entrada via argumentos de método, o método pode ser
usado de forma genérica. Nesse exemplo, se usarmos os valores do datapool
de teste para o horário de início e de término, e determinarmos outros valores
de entrada dinamicamente por meio de argumentos de método, o método é definido como mostrado na Listagem 6.
Listagem 6. Exemplo de programa para dar entrada em dados de forma dinâmica
public void runTraceAnalyzer(String schema,
String table,
String startDate,
String endDate)
{
schemaName().setText(schema);
tableName().setText(table);
startDate().setText(startDate);
startTime().setText(dpString("StartTime"));
endDate().setText(endDate);
endTime().setText(dpString("EndTime"));
ok().click();
} |
Automatizar a
verificação de resultados Caso sejam exibidos alguns resultados
no GUI, é fácil comparar os valores reais com os esperados usando o recurso
de ponto de verificação. Verificação
estatística de resultados Por exemplo, se for esperado obter a tabela descrita
na Figura 8, capture a tabela como ponto de verificação após começar a gravação e então pare
a gravação. Isso produz o programa descrito na Figura 9 e na Listagem 7.
Figura 8. Tabela
com alguns resultados
Figura 9. Programa gerado
com o recurso de ponto de verificação
Clique para ampliar
Listagem 7. Programa gerado
package verificationpoints;
import resources.verificationpoints.TestResult1Helper;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.object.interfaces.SAP.*;
import com.rational.test.ft.object.interfaces.WPF.*;
import com.rational.test.ft.object.interfaces.dojo.*;
import com.rational.test.ft.object.interfaces.siebel.*;
import com.rational.test.ft.object.interfaces.flex.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;
public class TestResult1 extends TestResult1Helper
{
public void testMain(Object[] args)
{
table().performTest(ResultTableVP());
}
} |
Copie o programa acima para criar o método mostrado na Listagem 8.
Se invocarmos o método, o Rational Functional Tester vai comparar
automaticamente os valores reais com os esperados.
Listagem 8. Exemplo de método para verificar resultados
public void verifyResult() {
table().performTest(ResultTableVP());
} |
Verificar
resultados dinamicamente Se quiser mudar os valores esperados dinamicamente,
use o método IFtVerificationPoint
vpManual(java.lang.String vpName, java.lang.Object expected,
java.lang.Object actual).performTest. O método vpManual tem três argumentos.
O primeiro argumento é para definir o nome do ponto de verificação exclusivo para
o projeto, o segundo, para definir um objeto esperado e o terceiro, para definir um
objeto real. Se quiser comparar valores em uma tabela como nesse exemplo, use o objeto
de classe com.rational.test.ft.vp.impl.TestDataTable no
segundo e terceiro argumentos do método vpManual. É possível
criar o objeto esperado como mostrado na Listagem 9. Também é possível especificar a regiãoa
ser comparada, o que é feito com o método setComparisonRegions.
Listagem 9. Exemplo de programa para criar uma tabela de resultados esperados
TestDataTable tbl = new TestDataTable();
tbl.setColumnHeader(0, "Table Name");
...
tbl.insert(new String[7], 0);
tbl.setCell(0, 1, "CUSTINFO");
...
TestDataTableRegions regions = new TestDataTableRegions();
regions.addRegion(TestDataTableRegion.allCells());
tbl.setComparisonRegions(regions.getRegions()); |
No exemplo seguinte, use o objeto de ponto de verificação como objeto esperado,
que foi criado capturando a tabela GUI como ponto de verificação no exemplo anterior.
Isso cria um objeto esperado. A seguir, modifique um valor do objeto. Para obter os
valores reais, é possível usar o método getTestData(String testDataType) do objeto da tabela obtido pelo mapa de objeto de teste, como
mostrado na Listagem 10. O argumento testDataType tem o valor
do tipo de propriedade exibido na janela do ponto de verificação.
É possível vê-lo na Figura 10. Nesse caso, esse valor é o "conteúdo visível".
Listagem 10. Exemplo de método para verificar um resultado de tabela
Public void verifyResult() {
TestDataTable tbl = (TestDataTable)ResultTableVP().getBaselineData();
tbl.setCell(0, 1, "CUSTHIST2");
vpManual("VP1", tbl, table().getTestData("visible contents")).performTest();
} |
Nesse programa, "CUSTHIST2" é definido em uma célula onde ficava "CUSTHIST".
Executar esse método resulta em erro, e as informações mostradas na
Figura 10 são obtidas.
Figura 10. Resultado
de detalhe em um ponto de verificação (Tabela)
Clique para ampliar
O exemplo anterior analisa o objeto
da tabela. Os outros objetos podem ser comparados como mostrado na Tabela 1. Tabela 1. Objetos que podem ser
comparados
| Tipo de GUI | Classe |
|---|
| Árvore | com.rational.test.ft.vp.impl.TestDataTree | | Lista | com.rational.test.ft.vp.impl.TestDataList | | Barra de menus | com.rational.test.ft.vp.impl.TestDataTree | | Sequência de caracteres | Sequência |
No caso do objeto de árvore, a Listagem 11
mostra um programa para adicionar um nó a um objeto de árvore capturado como ponto de
verificação.
Listagem 11. Exemplo de método para verificar um resultado de árvore
public void verifyResult() {
TestDataTree tree = (TestDataTree)GRDTreeVP().getBaselineData();
TestDataTreeNodes nodes = (TestDataTreeNodes)tree.getTreeNodes();
TestDataTreeNode node = (TestDataTreeNode)nodes.getRootNodes()[0];
node = (TestDataTreeNode)node.getChild(0);
node = (TestDataTreeNode)node.getChild(0);
node = (TestDataTreeNode)node.getChild(0);
TestDataTreeNode node2 = new TestDataTreeNode();
node2.setNode("GROUP2");
TestDataTreeNode[] n = new TestDataTreeNode[2];
n[0] = (TestDataTreeNode)node.getChild(0);
n[1] = node2;
node.setChildren(n);
vpManual("TreeVP1", tree, grdTree().getTestData("tree")).performTest();
} |
Ao executar esse programa, obtemos as seguintes informações (Figura 11).
Figura 11. Resultado
de detalhe em um ponto de verificação (Árvore)
No caso de lista, a Listagem 12 mostra um programa para
adicionar um item a um objeto lista capturado como ponto
de verificação.
Listagem 12. Exemplo de método para verificar um resultado de lista
public void verifyResult() {
TestDataList list = (TestDataList)TestListVP().getBaselineData();
TestDataElementList elemList = (TestDataElementList)list.getData();
TestDataElement elem = new TestDataElement();
elem.setElement("list3");
elemList.add(elem);
vpManual("ListVP1", list, list().getTestData("list")).performTest();
} |
Quando executamos esse programa, obtemos as seguintes informações (Figura 12).
Figura 12. Resultado
de detalhe em um ponto de verificação (Lista)
Teste de aplicativo que suporta múltiplos
idiomas Para testar um aplicativo em múltiplos idiomas,
use os arquivos de recursos que contenham chave e pares de valores
([KEY]=[VALUE]), nos quais os valores sejam exibidos
como GUI. Um exemplo de arquivo de recursos é aquele usado na classe
ResourceBundle do Java. As etapas para
configurar isso são as seguintes.
- A seguinte propriedade no arquivo ivory.properties do diretório
bin do Rational Functional Tester está ativado (por padrão, é
comentado.)
# Quando ativada, essa propriedade
permite busca de sequência em uma tabela da sequência localizada, se disponível
rational.test.ft.services.enable_localization=true |
- Arquivos de recursos do aplicativo que consistem em chave e pares de
valores copiados sob a pasta de recursos do projeto do Rational Functional
Tester após a mudança do nome base do arquivo para o nome do projeto do
Rational Functional Tester. Naturalmente, não há problema em, em vez disso,
criar o arquivo. O formato do nome do arquivo de recursos é:
- [nome do projeto do Rational Functional
Tester]_[idioma].properties
Por exemplo, no caso do nome do projeto do Rational Functional Tester
"DRAProject", o nome do arquivo de recursos em japonês é:
- Reinício do Rational Functional Tester.
- Abra o mapa de objeto de teste e mude os valores da propriedade que são valores
de exibição GUI para nomes de chave dos arquivos de recursos. Alguns nomes de propriedade, como o seguinte, têm valores de exibição GUI.
- accessibleContext.accessibleName
- .captionText
- name
- text
No caso do submenu, algum valor da propriedade é concatenado com
o nome do menu pai separado por sublinhado ("_"). Nesse caso, mude o peso
para 0.
Por exemplo, copie o arquivo de recursos em inglês para o japonês e acrescente
alguns caracteres japoneses diante de cada valor. Faça isso no GUI mostrado na Figura 13.
Figura 13. GUI de aplicativo
para o japonês
Clique para ampliar
Abra o mapa de objeto de teste e mude os valores de propriedade que são valores
exibidos GUI a nomes de chave do arquivo de recursos, como mostrado na Figura 14.
Figura 14. Insira
um nome de chave do arquivo de recursos no mapa de objeto de teste
Clique para ampliar
Quando pressionar a tecla Enter, o nome de chave é alterado para o valor real
no arquivo de recursos apropriado, como mostrado na Figura 15. O nome de chave
é armazenado dentro e o valor é alterado dinamicamente com base nos ajustes de
idioma. Ao dar um clique duplo no valor da propriedade para alternar de novo
para o modo de edição, é possível ver o nome da chave do arquivo de recursos.
Quando mudamos alguns valores do arquivo de recursos e depois reiniciamos o
Rational Functional Tester, vemos os valores alterados no mapa de objeto de teste.
Figura 15. Mudança
automática do nome de chave para o valor no arquivo de recursos
Clique para ampliar
A seguinte propriedade de nome tem seu valor concatenado
com o nome do menu pai, separado por sublinhado ("_"). Assim, seu peso é alterado
para 0 (Figura 16).
Figura 16. Mudança
do peso de uma propriedade para localizar um objeto GUI
Clique para ampliar
O que
aprendemos Este artigo descreveu o que fazer se não sabemos
que método é usado para manipular o GUI e como usar de forma eficaz o
datapool de teste e o ponto de verificação. Quando não sabemos que método
é usado para manipular o GUI, simulamos a ação GUI durante a gravação.
Depois, consultamos o programa gerado e fornecemos subclasses (com nomes
de método entendíveis), conforme a necessidade. Isso permite que eles sejam
usados facilmente a partir de outros programas. Usar o datapool de teste e
o ponto de verificação também lhe permite dar entrada em dados e verificar
os resultados do teste. O Rational Functional Tester também fornece
um recurso para aplicativos que suportam múltiplos idiomas. Esse artigo
explicou algumas dicas sobre esse recurso. O Rational Functional Tester
pode usar arquivos de recursos para múltiplos idiomas que contenham chave
e pares de valores para valores de exibição no GUI, de modo que é possível
testar também aplicativos que suportam múltiplos idiomas.
Recursos Aprender
Obter produtos e tecnologias
Discutir
Sobre os autores  | 
|  | Gou Nakashima is a member of the database tooling development team in the Yamato Software Development Laboratory (YSL), IBM Japan. |
 | |  | Masahiro Ohkawa é membro da equipe de desenvolvimento do conjunto de ferramentas para banco de dados do Yamato Software Development Laboratory (YSL), da IBM Japan. |
Avalie esta página
|  |