问题
I am not understanding how the scoping works on a test case.
[TestFixture]
class MockTests
{
[Setup]
private void StartTest()
{
IWebDriver driver = new ChromeDriver();
TestLogger logger = new TestLogger();
}
[TestCase(TestName = "mock1")]
{
//Problem is here. Driver and logger "does not exist in the current context"
driver.Navigate().GoToUrl("http://my.url.com");
logger.Out("Hello! I cannot be accessed!");
}
[TestCase(TestName = "mock2")]
{
//I now have a new instance of driver and logger in my mock2 test
driver.Navigate().GoToUrl("http://my.url.com");
logger.Out("Hello! I am a new Instance of TestLogger!");
}
[TearDown]
private void EndTest()
{
driver.Quit();
logger.PrintReport(TestContext.name, TestContext.status);
}
}
It seems to me the SetUp is pointless if you can't use it to access unique Instances of Objects across the tests. I see vars/objects used in a similar fashion, but with the vars/objects defined in the scope of the class; ie: private IWebDriver driver;
So if I have 25 tests inside a single test fixture and run them in parallel; the test functions could be talking to the wrong driver instead of creating unique Instance inside every TestCase.
How do I do this so I know my TestLogger and driver are indeed unique? How do I pass them between the SetUp Test and TearDown?
And TestLogger is just an example. It could be anything like a User object model:
public class User
{
public string fName{get; set;}
public string lName{get; set;}
//etc...
}
Maybe I just am not understand how the test should be setup.
回答1:
The variables driver
and logger
are local to your setup method. They go out of scope when the method exits.
If you want your tests to have access to anything setup in the setup method, then it has to be saved in a member variable.
Your "test cases" are not compilable. They are not methods. They do not appear to make any use of the arguments you are passing: "mock1" and "mock2". Most likely, you want to user [Test]
rather than [TestCases]
.
Most examples I have seen of web testing create the driver only once per test fixture, using [OneTimeSetUp] rather than [SetUp]. Do you really want to change the driver for each test? If so, and if you use a member variable, then you can't run your test cases in parallel because they will interfere with one another. Fortunately, for many test bases, running fixtures in parallel gives sufficiently good performance.
Update: Following your comment, it's clear you want to have a separate driver per test case. You have two choices...
Do not run test cases in parallel. Use
[Parallelizable]
on the fixture, causing it to run in parallel with other fixtures, but with it's test cases running serially because you don't haveChildren
in the scope. If you have a bunch of other fixtures, with which you can run in parallel, I think you will find this to be pretty effective.Run the cases in parallel, but don't use the SetUp method to create a driver. Instead, create it in each test. If it takes more than a line, use a method to return it. Each of your test cases will have a separate driver and you eliminate any chance of the tests stepping on one another.
FWIW, this example is leading me to want to take another look at how to provide better fixture separation for parallel tests without rewriting the whole framework.
回答2:
As Charlie said they must be a member variable to scope across the various tests inside a fixture(class).
My misunderstanding was thinking the SetUp and TearDown would be within the same scope as a test case. I had it in my head that was how NUnit worked...
This is definitely NOT the case. (no pun intended, ha)
So here is a working solution that shows unique instances that works across all the tests in parallel:
[TestFixture]
class MockTests
{
IWebDriver driver;
TestLogger logger;
[Setup]
private void StartTest()
{
//This instantiates a new driver and logger each test
driver = new ChromeDriver();
logger = new TestLogger();
}
[TestCase(TestName = "mock1")]
{
Console.WriteLine("Driver: " + driver.CurrentWindowHandle);
logger.Out("Hello! I am unique now! 1");
}
[TestCase(TestName = "mock2")]
{
Console.WriteLine("Driver: " + driver.CurrentWindowHandle);
logger.Out("Hello! I am unique now! 2");
}
[TestCase(TestName = "mock3")]
{
Console.WriteLine("Driver: " + driver.CurrentWindowHandle);
logger.Out("Hello! I am unique now! 3");
}
[TearDown]
private void EndTest()
{
driver.Quit();
logger.PrintReport(TestContext.CurrentContext.Test.Name, TestContext.CurrentContext.Result.Outcome.ToString());
}
}
来源:https://stackoverflow.com/questions/43988524/c-sharp-nunit-selenium-passing-objects-from-setup-to-testcase