資料表資料來源
請先確定您已熟悉 TAEF 的基本執行,並知道如何使用它 撰寫測試 ,再繼續進行本節。
既然您已撰寫並使用 TAEF 的基本測試自動化,您可以專注于可使用相同測試程式碼來處理不同資料集的案例。 基於此目的,TAEF 提供資料驅動測試的「資料表型」方法。 讓我們看看一個簡單的範例,瞭解如何撰寫資料驅動測試。
請考慮將大小和主題列印到主控台的簡單非資料驅動範例。 在此練習中,您會將此測試轉換為數據驅動測試。
1 namespace WEX { namespace TestExecution { namespace Examples
2 {
3 void DataDrivenTests::FirstTable()
4 {
5 int size = 12;
6 Log::Comment(String().Format(L"Size retrieved was %d", size));
7 }
8
9 void DataDrivenTests::SecondTable()
10 {
11 String theme = "Aero";
12 Log::Comment(L"Theme supplied as " + theme);
13 }
14 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */
定義資料
現在,您希望上述函式適用于一組大小和主題。 換句話說,您想要我們的函式可以使用的變體資料值。 若要這樣做,請在 XML 檔案中定義兩個數據表DataDrivenTests.xml:
1 <?xml version="1.0"?>
2 <Data>
3 <Table Id ="Table1">
4 <ParameterTypes>
5 <ParameterType Name="Size">Int32</ParameterType>
6 <ParameterType Name="Color">String</ParameterType>
7 <ParameterType Name="Transparency">Boolean</ParameterType>
8 </ParameterTypes>
9 <Row Priority="1" Owner="C2">
10 <Parameter Name="Size">12</Parameter>
11 <Parameter Name="Color">Blue</Parameter>
12 <Parameter Name="Transparency">True</Parameter>
13 </Row>
14 <Row Priority="2" Owner="wex">
15 <Parameter Name="Size">4</Parameter>
16 <Parameter Name="Color">White</Parameter>
17 <Parameter Name="Transparency">False</Parameter>
18 </Row>
19 <Row Owner="C2">
20 <Parameter Name="Size">9</Parameter>
21 <Parameter Name="Color">Black</Parameter>
22 <Parameter Name="Transparency">True</Parameter>
23 </Row>
24 </Table>
25 <Table id ="Table2">
26 <Row Description="ButtonTest" Owner="C2" Priority="1">
27 <Parameter Name="Control">Button</Parameter>
28 <Parameter Name="Theme">Aero</Parameter>
29 </Row>
30 <Row Description="ComboBoxTest" Priority="2">
31 <Parameter Name="Control">ComboBox</Parameter>
32 <Parameter Name="Theme">Classic</Parameter>
33 </Row>
34 <Row Description="ListviewTest" Owner="wex">
35 <Parameter Name="Control">Listview</Parameter>
36 <Parameter Name="Theme">AeroBasic</Parameter>
37 </Row>
38 </Table>
39 </Data>
您現在已定義兩個數據表 「Table1」 和 「Table2」。 您可以在相同的 XML 檔案中定義數個測試方法的資料表。
請注意,在 Table1 中,您已預先定義 ParameterTypes,並選擇 「Size」 做為整數。 ParameterTypes 區段是選擇性的。 根據預設,如果未提供參數類型資訊,則會儲存為字串。 這是 「Table2」 中所有參數的情況。
資料表內定義的每個「資料列」都是一組資料 (參數,) 您想要測試函式接受的值。 第 9、14 和 19 行定義第一個Table 函式會接受的 3 組資料。 同樣地,第 26、30 和 34 行會定義 SecondTable 的資料集。
請注意上述範例中的第 9、14、19、26、30 和 34 行 - 您可以定義資料列特定的中繼資料。 現在有方法可讓中繼資料資訊隨著相同函式的資料集而變更。 第一組資料 (第 9 行) 的優先順序為 1,第二組資料 (第 1) 4 行的優先順序為 2,第三組資料 (行 19) 預設為函式的優先順序。 所有資料列都會從資料表相關聯的函式繼承中繼資料。 如果在資料列層級再次指定相同的中繼資料,它會覆寫在函式層級定義的中繼資料值。
注意:除了支援的類型定義之外,原生和 Managed 程式碼的 XML 檔案架構定義相同。 如需如何定義資料的另一個範例,請參閱下面的一節的初始部分。 繼續進行原生資料驅動測試,以瞭解機器碼中允許的類型。
原生資料驅動測試
在定義資料集並準備好取用之後,您現在需要一種方式來將測試函式限定為數據驅動測試,並將它與定義資料集的資料表產生關聯。 這是透過撰寫測試時的額外中繼資料來完成:
1 namespace WEX { namespace TestExecution { namespace Examples
2 {
3 class DataDrivenTests
4 {
5 TEST_CLASS(DataDrivenTests);
6
7 BEGIN_TEST_METHOD(SecondTable)
8 TEST_METHOD_PROPERTY(L"DataSource", L"Table:DataDrivenTests.xml#Table2")
9 TEST_METHOD_PROPERTY(L"Priority", L"3")
10 END_TEST_METHOD()
11
12 BEGIN_TEST_METHOD(FirstTable)
13 TEST_METHOD_PROPERTY(L"Priority", L"4")
14 TEST_METHOD_PROPERTY(L"DataSource", L"Table:DataDrivenTests.xml#Table1")
15 END_TEST_METHOD()
16 };
17 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */
若要將 XML 資料表與測試產生關聯,請將 'DataSource' 中繼資料新增至測試的 方法。 透過此關聯 TAEF,將會使用指定的 DataSource 來驅動測試。 DataSource 值有三個部分:
- 'Table:' - 這會將資料來源識別為 XML 資料表。
- 'DataDrivenTests.xml' - 這是包含 XML 資料表的檔案。
- '#Table2' - 在 '#' delimeter 之後,'Table2' 值會識別要使用的 XML 檔內的特定資料表。 單一 XML 資料表資料來源可以包含多個資料表。 TAEF 會查看具有符合指定值之 'Id' 屬性之 Table 元素的 XML 檔案。
您可能已在上述範例中觀察到 「SecondTable」 是在 「FirstTable」 之前定義。 這表示 「SecondTable」 函式會在 「FirstTable」 函式之前執行,但您已定義 「Table1」,該資料表對應至 「FirstTable」,在 「Table2」 之前,即對應至 「SecondTable」 的資料表。 這是要強調, 在探索和執行資料驅動測試期間,資料表定義的順序無關。
隨著資料來源與測試方法的對應完成,您現在可以修改範例以從來源取得資料。 這麼做之前,請先看看已發佈的標頭檔 TestData.h。 感興趣的部分為:
1 class TestData
2 {
3 public:
4 template <typename T>
5 static HRESULT __stdcall TryGetValue(_In_z_ const wchar_t* pszString, T& result)
6 {
7 return Private::TestData<T>::TryGetValue(pszString, result);
8 }
9 };
第 5 行顯示要呼叫的 API,以便擷取函式中的資料。 請查看可用的 參數類型 以進行擷取。
確定 - 全部設定為重新寫入我們的範例:
1 namespace WEX { namespace TestExecution { namespace Examples
2 {
3 void DataDrivenTests::FirstTable()
4 {
5 Log::Comment(L"I am in first table");
6 int size;
7 if (SUCCEEDED(TestData::TryGetValue(L"size", size)))
8 {
9 VERIFY_ARE_NOT_EQUAL(size, 0);
10 Log::Comment(String().Format(L"Size retrieved was %d", size));
11 }
12 }
13
14 void DataDrivenTests::SecondTable()
15 {
16 Log::Comment(L"I am in second table.");
17 String theme;
18 if (SUCCEEDED(TestData::TryGetValue(L"theme", theme)))
19 {
20 Log::Comment(L"Theme supplied as " + theme);
21 }
22 }
23 } /* namespace Examples */ } /* namespace TestExecution */ } /* namespace WEX */
第 7 行和 18 行是變更的主要部分,以便讓測試資料驅動。 不是很大的變更。 請參閱執行資料驅動測試,以瞭解在執行資料驅動測試時如何充分利用 TAEF。
受控資料驅動測試
請考慮您想要在主控台上列印矩形座標的範例。 首先,將這些座標定義為 XML 檔案中的資料集。
1 <?xml version="1.0"?>
2 <Data>
3 <Table Id="FirstTable">
4 <ParameterTypes>
5 <ParameterType Name="Left">Int32</ParameterType>
6 <ParameterType Name="Right">String</ParameterType>
7 <ParameterType Name="Top">Integer</ParameterType>
8 <ParameterType Name="Bottom">Int32</ParameterType>
9 </ParameterTypes>
10 <Row Priority="1" Owner="C2" Description="Zero rect">
11 <Parameter Name="Left">0</Parameter>
12 <Parameter Name="Right">0</Parameter>
13 <Parameter Name="Top">0</Parameter>
14 <Parameter Name="Bottom">0</Parameter>
15 </Row>
16 <Row Priority="2" Owner="wex" Description="normal rect">
17 <Parameter Name="Left">12</Parameter>
18 <Parameter Name="Right">25</Parameter>
19 <Parameter Name="Top">10</Parameter>
20 <Parameter Name="Bottom">50</Parameter>
21 </Row>
22 <Row Owner="C2" Description="invalid rect">
23 <Parameter Name="Left">30</Parameter>
24 <Parameter Name="Right">15</Parameter>
25 <Parameter Name="Top">40</Parameter>
26 <Parameter Name="Bottom">10</Parameter>
27 </Row>
28 </Table>
29 </Data>
在此案例中,定義資料表範圍內的資料集「FirstTable」,此資料集定義于上述第 3 行。 您可以在相同的 XML 檔案中定義數個測試方法的資料表。
觀察 FirstTable 會預先定義 ParameterTypes,並呼叫 「Left」 做為 「Int32」。 ParameterTypes 區段是選擇性的。 根據預設,如果未提供參數類型資訊,則會儲存為 String。
請查看支援 的參數類型清單。
如果指定了任何其他資料類型,測試將會擲回警告,並將它視為 String。
注意:類型字串不區分大小寫,但應該完全拼字,如上所示。
資料表內定義的每個「資料列」都是一組資料 (參數) 您想要測試函式接受的值。 第 10、16 和 22 行定義函式的 3 組資料。
請注意上述範例中的第 10、16 和 22 行 - 您可以定義 Row 特定的中繼資料。 您現在有方法可讓中繼資料資訊隨著相同函式的資料集而變更。 第一組資料 (第 10 行) 的優先順序為 1,第二組資料 (第 1) 6 行的優先順序為 2,第三組資料 (第 22 行) 預設為函式的優先順序。 所有資料列都會從資料表相關聯的函式繼承中繼資料。 如果在資料列層級再次指定相同的中繼資料,它會覆寫在函式層級定義的中繼資料值。
注意:除了支援的類型定義之外,原生和 Managed 程式碼的 XML 檔案架構定義相同。 如需如何定義此資料的另一個範例,請參閱此頁面頂端的一節。
現在,您已定義所有資料。 下列範例示範如何存取它。
1 namespace WEX.Examples
2 {
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using System;
5 using System.Collections;
6 using WEX.Logging.Interop;
7 using WEX.TestExecution;
8
9 [TestClass]
10 public class CSharpDataDrivenTests
11 {
12 [TestMethod]
15 [DataSource("Table:CSharpDataDrivenTests.xml#FirstTable")]
16 public void First()
17 {
18 Console.WriteLine("Left is " + m_testContext.DataRow["Left"].ToString());
19
20 Log.Comment("In CSharpDataDrivenTests.First");
21 }
22
23 [TestMethod]
24 public void Second()
25 {
26 Log.Comment("In CSharpDataDrivenTests.Second");
27 Verify.IsTrue(true);
28 }
29
30 public TestContext TestContext
31 {
32 get { return m_testContext; }
33 set { m_testContext = value; }
34 }
35
36 private TestContext m_testContext;
37 }
38 }
將 XML 資料表與 Managed 程式碼中的指定測試方法建立關聯,非常類似于機器碼;只要套用 'DataSource' 中繼資料即可。 如同之前,它是由三個部分所組成:
- 'Table:' - 將資料來源識別為 XML 資料表。
- 'CSharpDataDrivenTests.xml' - 包含 XML 資料表的檔案。
- '#FirstTable' - 在 '#' 委派之後,'FirstTable' 值會識別要使用的 XML 檔內的特定資料表。 TAEF 會查看具有符合指定值之 'Id' 屬性之 Table 元素的 XML 檔案。
請注意,第二個函式不是資料驅動。 您可以選擇只讓部分測試成為資料驅動。 您也可以選擇讓每個測試在不同的 XML 檔案中定義其資料表。
在行 36 中,您會定義私人 TestCoNtext 屬性,例如 VSTS 建議 TestCoNtext 類別。 您也可以定義此屬性的公用評估者, (行 30 到 34) 。 在內部 TAEF 會將 TestCoNtext 的字典屬性與焦點中的對應資料集載入。
TestCoNtext 定義于 Microsoft.VisualStudio.TestTools.UnitTesting 中。 請參閱上述範例中的第 3 行。 您應該已在受控測試撰寫中包含此專案作為參考。 因此,撰寫資料驅動測試不需要其他參考。
在上述範例的第 18 行中,您會示範如何在 函式中擷取資料。 請注意,資料可在 m_testCoNtext.DataRow 中使用。
名稱而非索引來識別 DataRow
TAEF 可讓您擁有更有意義的 'Name' 屬性,而不是 Index 來識別 DataSource 中的任何 DataRow。 若要這樣做,只要在 DataSource 中的資料列層級新增 'Name' 中繼資料即可。 我們在此頁面上的第一個範例可以修改為使用此功能,如下所示:
1 <?xml version="1.0"?>
2 <Data>
3 <Table id ="Table1">
4 <ParameterTypes>
5 <ParameterType Name="Size">Int32</ParameterType>
6 <ParameterType Name="Color">String</ParameterType>
7 <ParameterType Name="Transparency">Boolean</ParameterType>
8 </ParameterTypes>
9 <Row Name='BlueTransparent' Priority="1" Owner="C2">
10 <Parameter Name="Size">12</Parameter>
11 <Parameter Name="Color">Blue</Parameter>
12 <Parameter Name="Transparency">True</Parameter>
13 </Row>
14 <Row Priority="2" Owner="wex">
15 <Parameter Name="Size">4</Parameter>
16 <Parameter Name="Color">White</Parameter>
17 <Parameter Name="Transparency">False</Parameter>
18 </Row>
19 <Row Name='BlackTransparent' Owner="C2">
20 <Parameter Name="Size">9</Parameter>
21 <Parameter Name="Color">Black</Parameter>
22 <Parameter Name="Transparency">True</Parameter>
23 </Row>
24 </Table>
25 ...
39 </Data>
在上述已修改的範例中,'BlueTransparent' 會對應至索引 0。 索引為 1 的資料列沒有指定特殊名稱,且索引為 2 的 Row 具有與其相關聯的 Name 'BlackTransparent。 您仍然可以使用選取查詢來尋找 'Table1' 中的索引 0 或 2,而且會找到正確的資料列。 但是,在執行或列出 dll 時,而不是看到:
<qualified name of the test method>#<index>
您將會改為看到:
<qualified name of the test method>#<name property provided at Row level>
在資料列層級提供 「Name」 屬性的資料列。 如果未針對任何 Row 提供 「Name」 屬性,例如上述索引 1 的情況,則預設為在方法的限定名稱上擁有 #< index >。
請注意,藉由在資料列層級提供「名稱」屬性,您基本上會變更 TAEF 以對應之 Row 資料解譯方法調用實例名稱的方式。
DataSource 作為執行時間參數
TAEF 支援提供資料來源作為執行時間參數。 此設定的語法如下:
te <test dll names> /p:<DataSource runtime name>=Table:<DataSoure XML file>#<Table Id>
在考慮撰寫測試時,您必須將 「p: < DataSource 執行時間名稱 > 」 指定為數據源。 請記住,您必須在執行時間指定完整字串 - XML 檔案名以及資料表識別碼。 如果您的資料來源是在執行時間提供,則 TableId 不預期會以測試中繼資料的形式提供。 「Table:」 前置詞會指定您要尋找資料表資料來源。
您可以使用發行共用上可用的其中一個範例來試用:
te Examples\CPP.RuntimeDataSource.Example.dll /p:MyDataSource=Table:RuntimeDataSourceExample.xml#SimpleTable
DataSource 作為資源
TAEF 可讓您將 DataSource 新增為測試模組的資源,只要符合下列條件:
如果是原生測試模組,您可以將 DataSource 指定為資源識別碼或資源名稱,以執行此動作。 以下是程式碼範例:
BEGIN_TEST_METHOD(ResourceNameDataSource)
TEST_METHOD_PROPERTY(L"DataSource", L"Table:MyResourceName#SimpleTable")
END_TEST_METHOD()
「MyResourceName」 是 ResourceDataSource.rc 檔案中所定義的資源名稱,在此案例中為:
MyResourceName DATASOURCE_XML "ResourceDataSource.xml"
如果是 Managed 測試模組,只能以特定方式指定資源,如以下所示 的來源 檔案程式碼片段所示:
LANGUAGE_NEUTRAL_MANAGED_RESOURCES = CSharpAdvancedDataDrivenTests.xml
在指定 DataSource XML 檔案時,DataSource 中繼資料規格會維持不變。 與 Managed 程式碼中的案例類似,您可以讓資源名稱與 XML 檔案名相同。 因此,請務必瞭解 TAEF 會先尋找具有 DataSource 名稱的實際檔案是否存在。 如果找不到這類 XML 檔案,則只會繼續在測試模組中尋找具有指定資源名稱或識別碼的測試資源。由於將 DataSource 指定為資源需要重新編譯,因此您可以將 DataSource XML 檔案複製到與測試 dll 相同的位置,同時開發 (並將資源名稱命名為與 XML 檔案名相同的) ,以利用此設計。 完成測試之後,請將 XML 複製到程式碼目錄,然後重新編譯為資源。 別忘了從執行目錄刪除 XML 檔案! :)
範例逐步解說
若要瞭解資料表型資料驅動測試的各種層面,請閱讀一些更多範例逐步解說: