I run selenium tests, and I have created a custom Test Fixture attribute that I apply to each fixture 3 times, each time with a new driver so my tests can run 3 separate times in 3 separate browsers. It looks like this:
[TestFixture(typeof(InternetExplorerDriver))]
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(ChromeDriver))]
class Edit<TWebDriver> : BaseTest<TWebDriver> where TWebDriver : IWebDriver, new()
{
[Test]
public void Test()
{
//test code
}
}
For my test fixtures, I mirror the web applications views in a 1:1 ratio - so the Dashboard\Index view in the web app code would be the Dashboard\Index folder for my tests that test the same view, therefore the test organization is very strict.
I am running into an issue that there are certain tests that should not run in certain browsers, such as IE. The majority of the tests need to however. What I am trying to do is for each test fixture
Is there any way to get the Test Fixture typeof value at test run time so I can do the following (pseudo code)...:
[Test]
public void Test()
{
if(testFixture typeof is InternetExplorerDriver)
{
Assert.Ignore("test not to be run in IE");
}
// all the test code
}
Please try the code modified below.
[TestFixture(typeof(InternetExplorerDriver))]
[TestFixture(typeof(FirefoxDriver))]
[TestFixture(typeof(ChromeDriver))]
class Edit<TWebDriver> : BaseTest<TWebDriver> where TWebDriver : IWebDriver, new()
{
private TWebDriver webDriver;
public Edit(TWebDriver webDriver)
{
this.webDriver = webDriver;
}
[Test]
public void Test()
{
//test code
if (this.webDriver.GetType() == typeof(InternetExplorerDriver))
{
Assert.Ignore("test not to be run in IE");
}
}
}
Related
I have a question on running UnitTests sequentially. Unfortunately in scenario it is not an option to run them parallel or mock the database. The project is written in .NET core 3.1 and the UnitTests need to execute database operations before and after a Unittest has run.
After reading https://www.meziantou.net/mstest-v2-execute-tests-in-parallel.htm and a lot of other articles about sequential UnitTesting I came up with this (simplified):
BaseClass:
namespace XY.Test
{
[TestClass]
public class BaseTest: TimerModel
{
private static readonly DbCreator Creator = new DbCreator();
public static readonly DbConnectionManager ConnectionManager = new DbConnectionManager();
[TestInitialize]
public void BaseTestInitialize()
{
CreateTestData();
}
[TestCleanup]
public void BaseTestCleanup()
{
RemoveTestData();
}
public void CreateTestData()
{
RemoveTestData();
Creator.ExecuteSqlFromScript(ConnectionManager, #"Resources\CreateTestData.sql");
}
public void RemoveTestData()
{
Creator.ExecuteSqlFromScript(ConnectionManager, #"Resources\EmptyTestDataTables.sql");
}
}
}
TestClass:
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.ClassLevel)] //<-- Also tried out Workers = 1 and Scope = ExecutionScope.MethodLevel
namespace XY.Test.Models
{
[TestClass]
public class TerminalConfigModelTest: BaseTest
{
[TestMethod]
[DoNotParallelize]
public void TestMethod1()
{
...
}
[TestMethod]
[DoNotParallelize]
public void TestMethod2()
{
...
}
}
}
For some reason, no matter what I do, the UnitTests are being executed parallel. What do I have to change in order to have them executed sequentially?
When I execute all tests in the test class, the TestInitialize of the base class is called twice before the TestCleanup is run. This causes the CreateTestData method to fail as indexes prevent a double insert of the test data.
What I would expect:
TestInitialize1 is called
TestMethod1 is executed
TestCleanup1 is called
TestInitialize2 is called
TestMethod2 is executed
TestCleanup2 is called
...
What happens:
TestInitialize1 is called
TestMethod1 is executed
TestInitialize2 is called before TestCleanup1 is called
TestMethod2 execution fails
Am I missunderstanding the [DoNotParallelize] option?
Paralelism isn't the problem here, my tests are definitely sequential and [ClassCleanup] also screwed me over. It's just unintuitive and weird, more info here.
I wanted to use ordered tests but it seems it's a legacy functionality only in MSTest-v1 and new versions of Visual Studio don't even support it.
Best thing i can tell you now is just don't use [ClassCleanup].
Use [TestCleanup] or [AssemblyCleanup].
I am launching the amazon url using chrome drive instance and I want to share the same session in which I have launched the amazon in all test methods. Here is the code for the same.
Can somebody tell me how to share the session from one method to another?
public class UnitTest1
{
IWebDriver chromeDriver = null;
[Fact]
public void Launch_Amazon_WithSearching()
{
amazonUrl = "https://www.amazon.in/";
chromeDriver = new ChromeDriver(#"C:\Projects\Install\ChromDriver");
chromeDriver.Navigate().GoToUrl(amazonUrl);
chromeDriver.Manage().Window.Maximize();
//here we are looking for search textbox and then entering a new value
IWebElement searchElement = chromeDriver.FindElement(By.Id("twotabsearchtextbox"));
searchElement.SendKeys("bluetooth earphones");
searchElement.SendKeys(Keys.Enter);
}
[Fact]
public void Amazon_OpenSearchedItem_And_AddToCart()
{
//here we are finding the elements from the searched results.
IWebElement searchedElement = chromeDriver.FindElement(By.XPath("//*[#id='search']//span[contains(text(),'Raging Red')]"));
searchedElement.Click();
//Here we are getting the new window name and then setting the chrome driver window to that new window
string newWindowName = chromeDriver.WindowHandles.Where(x => x != chromeDriver.CurrentWindowHandle).FirstOrDefault();
chromeDriver.SwitchTo().Window(newWindowName);
//this is for clicking add to cart button
IWebElement addToCartElement = chromeDriver.FindElement(By.Id("add-to-cart-button"));
addToCartElement.Click();
Assert.NotNull(addToCartElement);
}
}
The usage of FactAttribute reveals that you're using xUnit.
xUnit documentation:
xUnit.net creates a new instance of the test class for every test that is run, so any code which is placed into the constructor of the test class will be run for every single test.
That means fields won't help you to share the Chromedriver instance between test methods.
What you need is a fixture class - xUnit will make sure to create an instance of this class shared across tests methods. If your fixture class implements IDisposable, xUnit will call the dispose method after the methods of the class have run.
public class ChromeDriverFixture
{
public ChromeDriverFixture()
{
Driver = new ChromeDriver(#"C:\Path\To\ChromeDriver");
Driver.Manage().Window.Maximize();
}
public IWebDriver Driver { get; }
}
public class UnitTest1 : IClassFixture<ChromeDriverFixture>
{
private ChromeDriverFixture _fixture;
public UnitTest1(ChromeDriverFixture fixture)
{
_fixture = fixture;
}
[Fact]
public void Launch_Amazon_WithSearching()
{
const string amazonUrl = "https://www.amazon.in/";
_fixture.Driver.Navigate().GoToUrl(amazonUrl);
// ...
}
}
i am asking how to run multiple test method in order that they are in same file.
For example i have this Unit Test File name
public class UniTest1
{
[TestMethod]
public void Login()
[TestMethod]
public void Logout()
[TestMethod]
public void SignIn()
[TestMethod]
public void ForgetPassword()
}
I want them in this order:
Login()
Logout()
ForgetPassword()
SignIn()
Just to clarify i want this order to check if this email already exist or not
If you structure your test cases to contain the code for the setup, action and assertions for that particular case, you do not need to run them in any particular order. A good advice would be to aim to not have any dependencies between the test cases, for instance, you should need to depend upon a "Login" test to have run prior to "LogOut". Instead the setup of the test code in the "LogOut" case would initiate the logged in session and set the stage for the "LogOut" action to happen.
If you find that multiple test cases share common setup code and teardown code, you could use the TestInitialize and TestCleanup properties on some methods, as such:
namespace UserInteractionTests
{
[TestClass]
public class UserAuthenticationTestt
{
[TestInitialize]
public void TestSetup()
{
/* Put your common initialization code here */
}
[TestMethod]
public void AnAuthorizedUserCanLogin()
{
/* put your setup, action and assertion here
from your system under test
*/
}
[TestMethod]
public void ALoggedInUserCanLogOut()
{
/* put your setup, action and assertion here
from your system under test
*/
}
[TestCleanup]
public void TestCleanup()
{
/* Put your common teardown code here.. */
}
}
}
You're setting up one big Test with multiple steps but not four dedicated tests.
Here an example:
public class UniTest1
{
[TestMethod]
public void LoginSuccess()
{
// Try to Log in
o.Login("user", "pw");
Assert.AreEqual(true, o.ImLoggedIn);
}
[TestMethod]
public void LoginWrongPw()
{
// Try to Log in
o.Login("user", "wrongpw");
Assert.AreEqual(false, o.ImLoggedIn);
}
[TestMethod]
public void LogOutSuccess()
{
// Login
o.Login("user", "pw");
// Check if steup is completed
Assert.AreEqual(true, o.ImLoggedIn);
bool ok = o.LogOut();
Assert.AreEqual(true, ok);
}
[TestMethod, ExpectedException(NotLoggedInException)]
public void LogOutNoLogout()
{
// Try to Log in
Assert.AreEqual(false, o.ImLoggedIn);
bool ok = o.LogOut();
}
}
As you can see every test is independend from the others.
If you need a logout-test you have to setup the environment for it and not "hope" that other tests to so.
I am new to C#, i am not able to make driver thread safe. I am able to open the two browser as soon as second browser opens, first driver lose its references.
below is my code i have three class
namespace TestAutomation{
[TestFixture]
[Parallelizable(ParallelScope.Children)]
public class UnitTest1 : Setup
{
[Test, Property("TestCaseID","123")]
public void TestMethod1(this IWebDriver driver1)
{
driver1.Navigate().GoToUrl("https://www.google.com");
driver1.FindElement(By.Name("q")).SendKeys("test1");
Thread.Sleep(10000);
}
[Test, Property("TestCaseID", "234")]
public void TestMethod2()
{
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.Name("q")).SendKeys("test2");
Thread.Sleep(15000);
}
}}
Setup Class
namespace TestAutomation{
public class Setup:WebDriverManager
{
[SetUp]
public void setupBrowser()
{
driver = new ChromeDriver("C:\\Users\\Downloads\\chromedriver_win32");
}
[TearDown]
public void CloseBrowser()
{
driver.Close();
driver.Quit();
// driver.Close();
//driver.Quit;
}
}}
Webdrivermanager
namespace TestAutomation{
public class WebDriverManager
{
public IWebDriver driver { get; set; }
}
}
i am looking for a solution like ThreadLocal injava where i can get and set the driver for each thread in the setup method
Remove the SetUp & TearDown Attributes for the methods and call them explicitly. When you use these method attributes, it starts sharing resources across tests in the same class or inherited classes.
The below solution works perfectly fine. I have developed a project in which you can execute browser tests in parallel (method level parallelization). You can modify the project as per your needs.
Project Link: www.github.com/atmakur
[TestFixture]
class Tests
{
[Test]
public void Test1
{
using(var testInst = new TestCase())
{
testInst
.Init()
.NavigateToHomePage();
}
}
}
public class TestBase:IDisposable
{
private IWebDriver BaseWebDriver;
private TestContext _testContext;
public NavigatePage Init()
{
_testContext = TestContext.CurrentTestContext;
BaseWebDriver = new ChromeDriver();
.
.
.
}
public override void Dispose()
{
//Kill Driver here
//TestContext instance will have the AssertCounts
//But The Testcontext instance will have the result as Inconclusive.
}
}
You are doing two contradictory things:
Using a new browser for each test.
Sharing the browser property between the tests.
You should do one or the other. If you want to create a new browser for each test, don't store a reference to it where the other test also accesses it.
Alternatively, use OneTimeSetUp and OneTimeTearDown and only create the browser once. However, in that case, you can't run the tests in parallel.
I have the following:
[TestFixture]
public class SmokeTest : BaseTest
{
[Test(Description = "Should Do This")]
public void ShouldDoThis()
{
//Tests,Assertions,etc
}
[Test(Description = "Should Do That")]
public void ShouldDoThat()
{
//Tests,Assertions,etc
}
}
With BaseTest defined as:
[TestFixture]
public class BaseTest
{
[TestFixtureSetUp]
public void SetUp()
{
// set up browsers
}
[TearDown]
public void Dispose()
{
// dispose browsers
}
}
The goal is to have the selenium browsers' drivers created once per testFixture (// set up browsers), then at the end of the Fixture, torn down. Right now the browsers are being killed after the first test though, and the second test fails with some "Unable to connect to the remote server" error.
I'd like to target the first problem here - why is the TearDown method being called after the first test?
You need to use the TestFixtureTearDown attribute instead of the TearDown attribute in your base test. The TestFixtureTearDown attribute will cause the method to be run only once at the end of all of the tests in the fixture.