我正在使用Visual Studio 2012测试框架(我猜这是MSTest)。我有一些代码需要在运行各种testmethod之前运行一次。 ClassInitialize看起来很完美,直到我得知它必须是静态的。
首先,我有一个ChromeDriver的实例变量:
private ChromeDriver driver;
我想我需要这样的东西,但是非静止的:
[ClassInitialize]
public static void Initialize() {
ChromeOptions options = new ChromeOptions();
options.AddArgument("test-type");
options.AddArgument("start-maximized");
options.LeaveBrowserRunning = true;
driver = new ChromeDriver(@"C:\MyStuff", options);
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(4));
}
上面没有编译,因为在这个静态方法中正在新建类实例。但是我被迫使它变为静态,或者运行时错误导致“这必须是静态方法”和“错误签名”等。
如果我在类构造函数或TestInitialize方法中启动我的ChromeDriver(声明为类变量),一切正常但为每个测试打开一个新的浏览器窗口。因此,当我有50种测试方法时,我将打开50个Chrome实例,这很糟糕。
我只想在每次测试中重复使用driver
实例,而不必每次都启动一个新实例,这会打开一个新的浏览器。
如何做到这一点?
答案 0 :(得分:3)
我不确定它是否真的是最佳方法,但您可以将其设为静态变量 - 从实例方法访问静态变量很方便(你的测试)毕竟。
请注意,如果您尝试并行运行测试,则可能会出现问题。它可能值得调查测试实例生命周期是什么 - 在哪里可以使用一个实例进行多个测试,在这种情况下,在构造函数中初始化实例变量可能是另一种合理的方法。
(除非实际上需要很长时间来初始化驱动程序,否则我很想在每次测试的基础上创建它...)
答案 1 :(得分:0)
假设您的测试类包含10个测试。为了进行适当的测试,您的测试不应受其他测试的影响,您的测试也不应影响其他测试。
为了强制执行此操作,单元测试的开发人员定义每个测试都在其自己的测试类对象中运行。这使您可以自由地更改测试类对象中的变量,而不会影响其他测试。
您希望初始化程序只运行一次,并且所有测试都使用相同的变量。每个测试都在自己的测试对象中运行,因此这些变量必须是常见的。最简单的方法是静态变量。
但是,如果您不想使用静态变量,请考虑使用the singleton design pattern。唯一的单例对象包含在任何测试开始之前要初始化的变量。
private class MySingleton
{
public static MySingleTon GetInstance()
{
if (theOneAndOnlyInstance == null)
{
theOneAndOnlyInstance = new MySingleton(...);
}
return theOneAndOnlyInstance;
}
private static MySingleton theOneAndOnlyInstance = null;
private MySingleton(...)
{
... // initialize the non-static test variables
}
#region test variables
public int TestVariableX {get; set;}
...
#endregion test variables
}
[TestMethod}
public void MyTest()
{
var myTestVariables = MySingleton.GetInstance();
...
}
优点是在任何人使用它们之前,不会创建或初始化测试变量。构造函数是私有的,因此唯一可以创建对象的是静态函数GetInstance()。
答案 2 :(得分:0)
我不确定这是否是最好的方法,但似乎可行。 这里唯一需要的是唯一的测试方法名称部分。
private const string TEST_METHOD_UNIQUE_NAME_PART = "test";
private static TestContext _testContext;
private static bool _isPreconditionCompleted;
private static int _numberOfCompletedTests;
private int NumberOfTestMethodsInClass
{
get
{
var className = _testContext.FullyQualifiedTestClassName.Split('.').Last().Trim();
var currentType = Assembly.GetExecutingAssembly().GetExportedTypes()
.Where(r => r.Name.Trim() == className).First();
return currentType.GetMethods().Where(r => r.Name.ToLower()
.Contains(TEST_METHOD_UNIQUE_NAME_PART)).Count();
}
}
[ClassInitialize]
public static void ClassSetUp(TestContext testContext)
{
_testContext = testContext;
_isPreconditionCompleted = false;
_numberOfCompletedTests = 0;
}
[TestInitialize]
public void SetUp()
{
if (!_isPreconditionCompleted)
{
PreConditionMethod();
}
}
[TestCleanup]
public void TearDown()
{
_numberOfCompletedTests++;
if (_numberOfCompletedTests == NumberOfTestMethodsInClass)
{
PostConditionMethod();
}
}
private void PreConditionMethod()
{
// Your code
_isPreconditionCompleted = true;
}
private void PostConditionMethod()
{
// Your code
}