如何在不重复工作的情况下跨多个框架(互联网浏览器)使用自动化集成测试?
How can I use automated integration tests across multiple frameworks (internet browsers) without duplicating effort?
为了提供更多细节,我们进行了一系列测试,希望在三个框架(使用 Selenium 进行 UI 刺激)中进行复制:IE、Mozilla 和 Chrome。第一个解决方案是在单独的测试 class 中复制测试,即每个测试 class 具有相同的 20 个测试用例,但构造函数中的框架不同。第二种解决方案是使用每个框架类型作为输入的参数化输入(或 XUnit 理论):
/// <summary>
/// The non-default constructor that initializes
/// necessary instances of objects that are being used
/// </summary>
public VerifyViewUsingChrome() {
_testBases = new Dictionary<FunctionalTestBase.DriverType, TestBase>();
_testBases.Add(FunctionalTestBase.DriverType.Chrome, new TestBase(FunctionalTestBase.DriverType.Chrome));
_testBases.Add(FunctionalTestBase.DriverType.IE, new TestBase(FunctionalTestBase.DriverType.IE));
_testBases.Add(FunctionalTestBase.DriverType.FireFox, new TestBase(FunctionalTestBase.DriverType.FireFox));
}
/// <summary>
/// Our simple country display test.
/// </summary>
[InlineData(FunctionalTestBase.DriverType.Chrome)]
[InlineData(FunctionalTestBase.DriverType.FireFox)]
[InlineData(FunctionalTestBase.DriverType.IE)]
[Theory]
public void TestADisplayedForACountry(FunctionalTestBase.DriverType testBase) {
_testBases[testBase].TestADisplayedForACountry();
}
此实现的问题在于所有 3 个实现都必须 运行ning 用于每个测试,这需要一些开销。理想情况下,我们将 运行 所有 IE 测试,然后构建 Firefox 框架和 运行 这些测试,然后再继续 Chrome。
可能无法使用测试框架,但因为我们可以方便地与我们的构建服务器搭配使用,所以保留测试格式将是理想的。
我刚刚意识到解决方案比我想象的要简单。在每次测试之前都会调用构造函数,因此无论测试如何进行,框架启动和撕裂都会发生 运行(这是有道理的,因为您不希望之前的测试有任何渗漏)。
我们决定这样做:
/// <summary>
/// The non-default constructor that initializes
/// necessary instances of objects that are being used
/// </summary>
public VerifyViewUsing() { }
/// <summary>
/// Our simple country display test.
/// </summary>
[InlineData(FunctionalTestBase.DriverType.Chrome)]
[InlineData(FunctionalTestBase.DriverType.FireFox)]
[InlineData(FunctionalTestBase.DriverType.IE)]
[Theory]
public void TestADisplayedForACountry(FunctionalTestBase.DriverType testBaseType) {
TestBase testBase = new TestBase(testBaseType);
testBase.TestADisplayedForACountry();
}
这几乎完全符合我们的预期。每个测试都是独立的,跨框架重复,并且 运行 结果与所使用的框架相关联。
编辑:实际更好的方法是:
public static IEnumerable<object[]> DriverTypes {
get {
// Or this could read from a file. :)
return new[]
{
new object[] { FunctionalTestBase.DriverType.Chrome },
new object[] { FunctionalTestBase.DriverType.IE},
new object[] { FunctionalTestBase.DriverType.FireFox}
};
}
}
/// <summary>
/// Verifies that Brucellosis is displayed in the Disease List for
/// Zimbabwe
/// </summary>
[Theory, MemberData("DriverTypes")]
public void TestClickingADiseaseLinkDisplaysACreatePage(FunctionalTestBase.DriverType testBaseType) {
TestBase testBase = new TestBase(testBaseType);
testBase.TestClickingADiseaseLinkDisplaysACreatePage();
}
这使您可以一次定义框架,然后在整个项目中使用它们。
为了提供更多细节,我们进行了一系列测试,希望在三个框架(使用 Selenium 进行 UI 刺激)中进行复制:IE、Mozilla 和 Chrome。第一个解决方案是在单独的测试 class 中复制测试,即每个测试 class 具有相同的 20 个测试用例,但构造函数中的框架不同。第二种解决方案是使用每个框架类型作为输入的参数化输入(或 XUnit 理论):
/// <summary>
/// The non-default constructor that initializes
/// necessary instances of objects that are being used
/// </summary>
public VerifyViewUsingChrome() {
_testBases = new Dictionary<FunctionalTestBase.DriverType, TestBase>();
_testBases.Add(FunctionalTestBase.DriverType.Chrome, new TestBase(FunctionalTestBase.DriverType.Chrome));
_testBases.Add(FunctionalTestBase.DriverType.IE, new TestBase(FunctionalTestBase.DriverType.IE));
_testBases.Add(FunctionalTestBase.DriverType.FireFox, new TestBase(FunctionalTestBase.DriverType.FireFox));
}
/// <summary>
/// Our simple country display test.
/// </summary>
[InlineData(FunctionalTestBase.DriverType.Chrome)]
[InlineData(FunctionalTestBase.DriverType.FireFox)]
[InlineData(FunctionalTestBase.DriverType.IE)]
[Theory]
public void TestADisplayedForACountry(FunctionalTestBase.DriverType testBase) {
_testBases[testBase].TestADisplayedForACountry();
}
此实现的问题在于所有 3 个实现都必须 运行ning 用于每个测试,这需要一些开销。理想情况下,我们将 运行 所有 IE 测试,然后构建 Firefox 框架和 运行 这些测试,然后再继续 Chrome。
可能无法使用测试框架,但因为我们可以方便地与我们的构建服务器搭配使用,所以保留测试格式将是理想的。
我刚刚意识到解决方案比我想象的要简单。在每次测试之前都会调用构造函数,因此无论测试如何进行,框架启动和撕裂都会发生 运行(这是有道理的,因为您不希望之前的测试有任何渗漏)。
我们决定这样做:
/// <summary>
/// The non-default constructor that initializes
/// necessary instances of objects that are being used
/// </summary>
public VerifyViewUsing() { }
/// <summary>
/// Our simple country display test.
/// </summary>
[InlineData(FunctionalTestBase.DriverType.Chrome)]
[InlineData(FunctionalTestBase.DriverType.FireFox)]
[InlineData(FunctionalTestBase.DriverType.IE)]
[Theory]
public void TestADisplayedForACountry(FunctionalTestBase.DriverType testBaseType) {
TestBase testBase = new TestBase(testBaseType);
testBase.TestADisplayedForACountry();
}
这几乎完全符合我们的预期。每个测试都是独立的,跨框架重复,并且 运行 结果与所使用的框架相关联。
编辑:实际更好的方法是:
public static IEnumerable<object[]> DriverTypes {
get {
// Or this could read from a file. :)
return new[]
{
new object[] { FunctionalTestBase.DriverType.Chrome },
new object[] { FunctionalTestBase.DriverType.IE},
new object[] { FunctionalTestBase.DriverType.FireFox}
};
}
}
/// <summary>
/// Verifies that Brucellosis is displayed in the Disease List for
/// Zimbabwe
/// </summary>
[Theory, MemberData("DriverTypes")]
public void TestClickingADiseaseLinkDisplaysACreatePage(FunctionalTestBase.DriverType testBaseType) {
TestBase testBase = new TestBase(testBaseType);
testBase.TestClickingADiseaseLinkDisplaysACreatePage();
}
这使您可以一次定义框架,然后在整个项目中使用它们。