Classe controlada por dados
Verifique se você está familiarizado com a execução básica do TAEF e saiba como criar testes usando-o antes de prosseguir com esta seção. Talvez você também queira percorrer o passo a passo simples de exemplo de teste controlado por dados. Nesta seção, você fará uma classe de teste controlada por dados baseada em um teste baseado em dados baseado em tabela , mas a mesma abordagem se aplica a testes baseados em dados baseados em WMI ou PICT .
Quando usar uma classe controlada por dados?
Há momentos em que vários testes podem depender dos mesmos dados de entrada. Ao testar APIs, talvez você queira executar vários testes de API com os mesmos dados para obter uma visão consistente do comportamento da API. Ao executar testes de nível de cenário, convém garantir que todas as etapas em seu cenário sejam testadas com os mesmos dados. Nesses momentos, é útil especificar os dados de teste no nível da classe.
Criação de classe controlada por dados
Você especifica que uma determinada classe é controlada por dados de maneira semelhante à forma como você especifica que um determinado teste é controlado por dados. Você aplica os metadados do DataSource no nível da classe. O valor identifica a fonte de dados específica de interesse. O exemplo a seguir mostra como especificar essas propriedades para classes controladas por dados:
Código nativo
1 class 2 {
2 BEGIN_TEST_CLASS(DataDrivenClassExample)
3 TEST_CLASS_PROPERTY(L"DataSource", L"Table:DataDrivenClassExample.xml#ClassTable")
4 END_TEST_CLASS()
5
6 TEST_METHOD(Test1);
7 {
8 int size;
9 if (SUCCEEDED(<span class="style2">TestData::TryGetValue(L"size", size)</span>))
10 {
11 VERIFY_ARE_NOT_EQUAL(size, 0);
12 Log::Comment(String().Format(L"Size retrieved was %d", size));
13 }
14
15 String color;
16 if (SUCCEEDED(<span class="style2">TestData::TryGetValue(L"color", color)</span>))
17 {
18 Log::Comment(L"Color retrieved was " + color);
19 }
20 }
21 TEST_METHOD(Test2);
22 {
23 int size;
24 if (SUCCEEDED(<span class="style2">TestData::TryGetValue(L"size", size)</span>))
25 {
26 VERIFY_ARE_NOT_EQUAL(size, 0);
27 Log::Comment(String().Format(L"Size retrieved was %d", size));
28 }
29
30 String color;
31 if (SUCCEEDED(<span class="style2">TestData::TryGetValue(L"color", color)</span>))
32 {
33 Log::Comment(L"Color retrieved was " + color);
34 }
35 }
36 };
Código gerenciado
1 [TestClass]
2 public class CSharpDataDrivenClassExample
3 {
4 [ClassInitialize]
5 [DataSource("Table:CSharpDataDrivenClassExample.xml#ClassTable")]
6 public static void MyClassInitialize(Object testContext)
7 {
8 }
9
10 [TestMethod]
11 public void Test1()
12 {
13 int size = (int)m_testContext.DataRow["Size"];
14 Verify.AreNotEqual(size, 0);
15 Log.Comment("Size is " + size.ToString());
16
18 Log.Comment("Color is " + m_testContext.DataRow["Color"]);
19 }
20
21 [TestMethod]
22 public void Test2()
23 {
24 int size = (int)m_testContext.DataRow["Size"];
25 Verify.AreNotEqual(size, 0);
26 Log.Comment("Size is " + size.ToString());
27
28 Log.Comment("Color is " + m_testContext.DataRow["Color"]);
29 }
30
31 public TestContext TestContext
32 {
33 get { return m_testContext; }
34 set { m_testContext = value; }
35 }
36
37 private TestContext m_testContext;
38 }
Nestes exemplos, a linha 3 no exemplo de código nativo e a linha 5 no exemplo de código gerenciado são as maneiras recomendadas de especificar a fonte de dados para uma classe de teste controlada por dados no TAEF.
No exemplo de código gerenciado acima, as linhas 13, 18, 24 e 28 mostram como os dados são disponibilizados para os métodos de teste para código gerenciado.
No exemplo de código a seguir, as linhas 4, 11, 20 e 27 mostram como os dados são disponibilizados para os métodos de teste para código nativo. Observe que você disponibiliza os dados definidos na tabela (linhas) da classe controlada por dados para os métodos de teste na classe (Test1 e Test2) exatamente da mesma maneira que faria para um teste controlado por dados.
Você constrói o arquivo XML do DataSource para uma classe controlada por dados exatamente da mesma maneira que faria para um teste controlado por dados. Os exemplos a seguir mostram os arquivos XML para classes nativas e gerenciadas.
Nativo
1 <?xml version="1.0"?>
2 <Data>
3 <Table Id="ClassTable">
4 <ParameterTypes>
5 <ParameterType Name="Size">int</ParameterType>
6 </ParameterTypes>
7 <Row>
8 <Parameter Name="Size">4</Parameter>
9 <Parameter Name="Color">White</Parameter>
10 </Row>
11 <Row>
12 <Parameter Name="Size">10</Parameter>
13 <Parameter Name="Color">Black</Parameter>
14 </Row>
15 <Row>
16 <Parameter Name="Size">9</Parameter>
17 <Parameter Name="Color">Orange</Parameter>
18 </Row>
19 <Row>
20 <Parameter Name="Size">9</Parameter>
21 <Parameter Name="Color">Blue</Parameter>
22 </Row>
23 </Table>
24</Data>
Gerenciado
1 <?xml version="1.0"?>
2 <Data>
3 <Table Id="ClassTable">
4 <ParameterTypes>
5 <ParameterType Name="Size">Int32</ParameterType>
6 <ParameterType Name="Color">String</ParameterType>
7 </ParameterTypes>
8 <Row>
9 <Parameter Name="Size">4</Parameter>
10 <Parameter Name="Color">White</Parameter>
11 </Row>
12 <Row>
13 <Parameter Name="Size">10</Parameter>
14 <Parameter Name="Color">Black</Parameter>
15 </Row>
16 <Row>
17 <Parameter Name="Size">9</Parameter>
18 <Parameter Name="Color">Orange</Parameter>
19 </Row>
20 <Row>
21 <Parameter Name="Size">9</Parameter>
22 <Parameter Name="Color">Blue</Parameter>
23 </Row>
24 </Table>
25</Data>
Bastidores OU O que esperar?
Por padrão, quando você cria testes no TAEF, a ordem de execução dentro de uma classe é a mesma que a ordem na qual você codifica os métodos de teste na classe . Portanto, nos exemplos anteriores, Test1 sempre será executado antes do Test2. Como a classe que contém Test1 e Test2 é uma classe controlada por dados, todos os métodos de classe serão executados uma vez para cada LINHA de dados que você definiu no DataSource. Em outras palavras, Test1 e Test2 são executados para a Linha nº 0. Em seguida, esses métodos são executados na mesma ordem para a Linha nº 1 e assim por diante até que o TAEF execute todas as linhas.
Executando testes em uma classe controlada por dados
Se você executar os binários de teste de exemplo com a opção de comando /list , a ordem de execução da seção anterior ficará clara.
Nativo
TE.exe Examples\CPP.AdvancedDataDriven.Examples.dll /name:*class* /list
Test Authoring and Execution Framework v2.9.3k for x86
F:\ Examples\CPP.AdvancedDataDriven.Examples.dll
WEX::TestExecution::Examples::DataDrivenClassExample#0
WEX::TestExecution::Examples::DataDrivenClassExample#0::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#0::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#1
WEX::TestExecution::Examples::DataDrivenClassExample#1::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#1::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#2
WEX::TestExecution::Examples::DataDrivenClassExample#2::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#2::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#3
WEX::TestExecution::Examples::DataDrivenClassExample#3::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#3::Test2
Gerenciado
TE.exe Examples\CSharp.AdvancedDataDriven.Examples.dll /name:*class* /list
Test Authoring and Execution Framework v2.9.3k for x86
F:\ Examples\CSharp.AdvancedDataDriven.Examples.dll
WEX.Examples.CSharpDataDrivenClassExample#0
WEX.Examples.CSharpDataDrivenClassExample#0.Test1
WEX.Examples.CSharpDataDrivenClassExample#0.Test2
WEX.Examples.CSharpDataDrivenClassExample#1
WEX.Examples.CSharpDataDrivenClassExample#1.Test1
WEX.Examples.CSharpDataDrivenClassExample#1.Test2
WEX.Examples.CSharpDataDrivenClassExample#2
WEX.Examples.CSharpDataDrivenClassExample#2.Test1
WEX.Examples.CSharpDataDrivenClassExample#2.Test2
WEX.Examples.CSharpDataDrivenClassExample#3
WEX.Examples.CSharpDataDrivenClassExample#3.Test1
WEX.Examples.CSharpDataDrivenClassExample#3.Test2
Observe que os índices nos exemplos acima são semelhantes aos testes controlados por dados. Cada linha na classe controlada por dados é identificada por um índice. Assim como nos testes controlados por dados, você pode optar por dar a qualquer linha um Nome curto mais significativo especificando os metadados no nível linha no arquivo XML e imprimindo esse nome em vez do índice ao listar ou executar os testes.
Da mesma forma, você usa a opção /listproperties para confirmar se os dados estão realmente especificados e disponíveis no nível da classe.
Nativo
F:\ Examples\CPP.AdvancedDataDriven.Examples.dll
WEX::TestExecution::Examples::DataDrivenClassExample#0
Property[DataSource] = Table:DataDrivenClassExample.xml#ClassTable
Data[Color] = White
Data[Size] = 4
WEX::TestExecution::Examples::DataDrivenClassExample#0::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#0::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#1
Property[DataSource] = Table:DataDrivenClassExample.xml#ClassTable
Data[Color] = Black
Data[Size] = 10
WEX::TestExecution::Examples::DataDrivenClassExample#1::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#1::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#2
Property[DataSource] = Table:DataDrivenClassExample.xml#ClassTable
Data[Color] = Orange
Data[Size] = 9
WEX::TestExecution::Examples::DataDrivenClassExample#2::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#2::Test2
WEX::TestExecution::Examples::DataDrivenClassExample#3
Property[DataSource] = Table:DataDrivenClassExample.xml#ClassTable
Data[Color] = Blue
Data[Size] = 9
WEX::TestExecution::Examples::DataDrivenClassExample#3::Test1
WEX::TestExecution::Examples::DataDrivenClassExample#3::Test2
Gerenciado
F:\ Examples\CSharp.AdvancedDataDriven.Examples.dll
WEX.Examples.CSharpDataDrivenClassExample#0
Setup: MyClassInitialize
Property[DataSource] = Table:CSharpDataDrivenClassExample.xml#ClassTable
Data[Color] = White
Data[Size] = 4
WEX.Examples.CSharpDataDrivenClassExample#0.Test1
WEX.Examples.CSharpDataDrivenClassExample#0.Test2
WEX.Examples.CSharpDataDrivenClassExample#1
Setup: MyClassInitialize
Property[DataSource] = Table:CSharpDataDrivenClassExample.xml#ClassTable
Data[Color] = Black
Data[Size] = 10
WEX.Examples.CSharpDataDrivenClassExample#1.Test1
WEX.Examples.CSharpDataDrivenClassExample#1.Test2
WEX.Examples.CSharpDataDrivenClassExample#2
Setup: MyClassInitialize
Property[DataSource] = Table:CSharpDataDrivenClassExample.xml#ClassTable
Data[Color] = Orange
Data[Size] = 9
WEX.Examples.CSharpDataDrivenClassExample#2.Test1
WEX.Examples.CSharpDataDrivenClassExample#2.Test2
WEX.Examples.CSharpDataDrivenClassExample#3
Setup: MyClassInitialize
Property[DataSource] = Table:CSharpDataDrivenClassExample.xml#ClassTable
Data[Color] = Blue
Data[Size] = 9
WEX.Examples.CSharpDataDrivenClassExample#3.Test1
WEX.Examples.CSharpDataDrivenClassExample#3.Test2
Você pode aplicar todas as regras de execução à classe controlada por dados. Você pode basear sua consulta de seleção em qualquer coisa que possa listar na opção /listproperties .
Testes controlados por dados em uma classe controlada por dados
Você não está confinado de forma alguma por ter testes controlados por dados em uma classe controlada por dados. Essa abordagem pode ser útil ao escrever testes de API. Você pode manter os dados comuns para todos os testes em uma classe no nível da classe DataSource. Especifique os dados específicos do método de teste nos metadados do DataSource para o método que você marca como controlado por dados.
OBSERVAÇÃO: nesses casos, a ordem de execução está um pouco mais envolvida.
Os exemplos a seguir mostram como os dois binários de exemplo anteriores são renderizados com a opção de comando /list .
Nativo
TE.exe Examples\CPP.AdvancedDataDriven.Examples.dll /name:*nested* /list
Test Authoring and Execution Framework v2.9.3k for x86
F:\ Examples\CPP.AdvancedDataDriven.Examples.dll
WEX::TestExecution::Examples::NestedDataDrivenExample#0
WEX::TestExecution::Examples::NestedDataDrivenExample#0::Test1
WEX::TestExecution::Examples::NestedDataDrivenExample#0::Test2#0
WEX::TestExecution::Examples::NestedDataDrivenExample#0::Test2#1
WEX::TestExecution::Examples::NestedDataDrivenExample#0::Test2#2
WEX::TestExecution::Examples::NestedDataDrivenExample#0::Test2#3
WEX::TestExecution::Examples::NestedDataDrivenExample#1
WEX::TestExecution::Examples::NestedDataDrivenExample#1::Test1
WEX::TestExecution::Examples::NestedDataDrivenExample#1::Test2#0
WEX::TestExecution::Examples::NestedDataDrivenExample#1::Test2#1
WEX::TestExecution::Examples::NestedDataDrivenExample#1::Test2#2
WEX::TestExecution::Examples::NestedDataDrivenExample#1::Test2#3
WEX::TestExecution::Examples::NestedDataDrivenExample#2
WEX::TestExecution::Examples::NestedDataDrivenExample#2::Test1
WEX::TestExecution::Examples::NestedDataDrivenExample#2::Test2#0
WEX::TestExecution::Examples::NestedDataDrivenExample#2::Test2#1
WEX::TestExecution::Examples::NestedDataDrivenExample#2::Test2#2
WEX::TestExecution::Examples::NestedDataDrivenExample#2::Test2#3
WEX::TestExecution::Examples::NestedDataDrivenExample#3
WEX::TestExecution::Examples::NestedDataDrivenExample#3::Test1
WEX::TestExecution::Examples::NestedDataDrivenExample#3::Test2#0
WEX::TestExecution::Examples::NestedDataDrivenExample#3::Test2#1
WEX::TestExecution::Examples::NestedDataDrivenExample#3::Test2#2
WEX::TestExecution::Examples::NestedDataDrivenExample#3::Test2#3
Gerenciado
TE.exe Examples\CSharp.AdvancedDataDriven.Examples.dll /name:*nested* /list
Test Authoring and Execution Framework v2.9.3k for x86
F:\ Examples\CSharp.AdvancedDataDriven.Examples.dll
WEX.Examples.CSharpDataDrivenNestedExample#0
WEX.Examples.CSharpDataDrivenNestedExample#0.Test1
WEX.Examples.CSharpDataDrivenNestedExample#0.Test2#0
WEX.Examples.CSharpDataDrivenNestedExample#0.Test2#1
WEX.Examples.CSharpDataDrivenNestedExample#0.Test2#2
WEX.Examples.CSharpDataDrivenNestedExample#0.Test2#3
WEX.Examples.CSharpDataDrivenNestedExample#1
WEX.Examples.CSharpDataDrivenNestedExample#1.Test1
WEX.Examples.CSharpDataDrivenNestedExample#1.Test2#0
WEX.Examples.CSharpDataDrivenNestedExample#1.Test2#1
WEX.Examples.CSharpDataDrivenNestedExample#1.Test2#2
WEX.Examples.CSharpDataDrivenNestedExample#1.Test2#3
WEX.Examples.CSharpDataDrivenNestedExample#2
WEX.Examples.CSharpDataDrivenNestedExample#2.Test1
WEX.Examples.CSharpDataDrivenNestedExample#2.Test2#0
WEX.Examples.CSharpDataDrivenNestedExample#2.Test2#1
WEX.Examples.CSharpDataDrivenNestedExample#2.Test2#2
WEX.Examples.CSharpDataDrivenNestedExample#2.Test2#3
WEX.Examples.CSharpDataDrivenNestedExample#3
WEX.Examples.CSharpDataDrivenNestedExample#3.Test1
WEX.Examples.CSharpDataDrivenNestedExample#3.Test2#0
WEX.Examples.CSharpDataDrivenNestedExample#3.Test2#1
WEX.Examples.CSharpDataDrivenNestedExample#3.Test2#2
WEX.Examples.CSharpDataDrivenNestedExample#3.Test2#3
NOTA: A única restrição nesse caso é que as tabelas dos dois exemplos não podem estar no mesmo arquivo DataSource. Em outras palavras, o DataSource para a classe controlada por dados e o método de teste controlado por dados que ele contém devem ser diferentes.
Observe que o método Test2 em nossos exemplos é um teste controlado por dados em uma classe controlada por dados. Por exemplo, na linha WEX. Examples.CSharpDataDrivenNestedExample#3.Test2#0, #3 é o índice da classe e #0 é o índice para o teste controlado por dados dentro dessa classe. O Test2 pode acessar ambas as tabelas: os dados na linha da instância de classe à qual pertence e os dados na linha atual para sua própria tabela DataSource . Em outras palavras, os dados no nível da classe e os dados no nível do método de teste são agregados e estão disponíveis durante a execução do método de teste.
O que acontece no caso de dados conflitantes – se o mesmo nome de dados for especificado no nível da classe e no nível do método? O TAEF processa essa condição da mesma forma que processa as propriedades de metadados. Os dados especificados em uma Linha no nível do método substituem os dados especificados em uma Linha no nível da classe.
Por exemplo, considere o caso quando você tiver um parâmetro chamado Size especificado no nível da classe e no nível do método de teste. No nível da classe, Size é definido como do tipo String Array , mas no nível do método de teste, ele é definido como um int. Nesse caso, o tipo int substitui o tipo String Array no nível do método de teste, bem como nos métodos Setup e Teardown para o teste. No entanto, nos métodos Setup e Teardown no nível da classe, Size tem o tipo de dados String Array .
Se você tiver esses dados conflitantes em seu código, o TAEF mostrará um aviso durante a execução e listará as propriedades, mas os dados conflitantes não resultarão em nenhuma falha.