How do I Execute Code after a Test failed - c#

I am Creating Unit Tests for a Library. This Library Connects to a Datasource and then I am doing some testing Stuff afterwards the Datasource will be disconnected.
If one of the Tests fails, the Method is Terminated and I dont get to execute the Disconnection Function.
Here's a Sample to understande the above description:
[TestMethod]
public void Test()
{
var datasourceObject = new DatasourceObject("location-string");
datasourceObject.Connect();
// Do some Stuff with Asserts
datasourceObject.Disconnect(); // must be executed
}
Is There any Bestpractice to achieve that?

If you use resource in other tests, then move it to class fields and use [TestInitialize] and [TestCleanup] to get and free that resource:
private Foo datasourceObject;
[TestInitialize]
public void TestInitialize()
{
this.datasourceObject = new DatasourceObject("location-string");
this.datasourceObject.Connect();
}
[TestMethod]
public void Test()
{
// Do some Stuff with Asserts
}
[TestCleanup]
public void TestCleanup()
{
this.datasourceObject.Disconnect();
}
If you use resource in this test only, then use either try..finally
[TestMethod]
public void Test()
{
try
{
var datasourceObject = new DatasourceObject("location-string");
datasourceObject.Connect();
// Do some Stuff with Asserts
}
finally
{
datasourceObject.Disconnect(); // must be executed
}
}
Or using statement if resource is disposable:
[TestMethod]
public void Test()
{
using(var datasourceObject = new DatasourceObject("location-string"))
{
datasourceObject.Connect();
// Do some Stuff with Asserts
}
}

Related

Do long term operation only once per NUnit test run

what I try to do is make a long term operation only once per all Unit tests.
OneTimeSetup is not the soltution I'm searching for :).
I want to do this:
Before starting the first test do a long time operation for example load a large file.
Start TestFixture 1
Run Test 1 (Result of step 1 must be available)
Run Test 2 (Result of step 1 must be available)
Start TestFixture 2
Run Test 1 (Result of step 1 must be available)
Run Test 2 (Result of step 1 must be available)
... and so on
Cleanup
Is this possible?
Any suggestions
Greetings Michael
You could use a separate class with a static constructor:
public static class LongTimeOperation
{
static LongTimeOperation()
{
Thread.Sleep(10000);
Resource = (++count).ToString();
}
public static string Resource { get; set; }
private static int count = 0;
}
[TestFixture]
public class TestFixture1
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
resource = LongTimeOperation.Resource;
}
[Test]
public void Test1() => Assert.That(resource, Is.EqualTo("1"));
[Test]
public void Test2() => Assert.That(resource, Is.EqualTo("1"));
private string resource;
}
[TestFixture]
public class TestFixture2
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
resource = LongTimeOperation.Resource;
}
[Test]
public void Test1() => Assert.That(resource, Is.EqualTo("1"));
[Test]
public void Test2() => Assert.That(resource, Is.EqualTo("1"));
private string resource;
}

NUnit Check if button was click

I am learning how to do unit testing. I tried to search for how to do testing for a button click event but couldn't find an answer that I could understand.
How can I check if TextBlock_MouseDown event was raised and followed by reponse from PostMethod, which must not be null. My issue is, I can't find a way or don't know how to check TextBlock_MouseDown event using NUnit.
public partial class MainWindow : Window
{
public MainWindow(){
InitializeComponent();
}
public void TextBlock_MouseDown(object sender, MouseButtonEventArgs e){
//Check return value from PostMethod
string reponse = PostMethod("myurlhere");
}
public static String PostMethod(String val){
//Code
}
}
[TestFixture]
public class TestClass
{
[Test]
public void PostMethod_IsAlive_returnHello()
{
//ARRANGE
String url = "myurlhere";
//ACT
string response = MainWindow.PostMethod(url);
//ASSERT
Assert.AreEqual("\"Hello\"", response);
}
}
If you want to to test your UI, you should use a test library for UI-Testing.
For example FlaUI (https://github.com/Roemer/FlaUI).
NUnit is used to test your code behind. For example if you want to check if PostMethod() is returning a specific value.
If you only want to check the result of PostMethod(), outsource the method to another class and test it (MainWindow will now use OutsourcedClass.PostMethod() in its code behind).
outsourced class
public class OutsourcedClass
{
public string PostMethod(string url)
{
return url;
}
}
unit test
public class OutsourcedClassTest
{
private OutsourcedClass _Instance;
[SetUp]
public void Setup()
{
_Instance = new OutsourcedClass();
}
[Test]
public void PostMethodTest()
{
string url = "foo";
Assert.AreEqual(url, _Instance.PostMethod(url));
}
}

Can setup and teardown be called for each of the Test Cases?

[Setup]
public void RunBeforeAnyTest()
{
}
[TearDown]
public void RunAfterEveryTest()
{
}
[Test]
public void Test1()
{
}
[TestCase("case1")]
[Testcase("case2")]
public void Test2()
{
}
In above example, the Setup and TearDown gets executed before and after Test1 and Test2. But I want it to execute before and after individual test case in Test2. Is it possible with nunit framework? How can I achieve this?
After correcting for some typos:
[TestFixture]
public class Class1
{
[SetUp]
public void RunBeforeAnyTest()
{
Console.WriteLine("RunBeforeAnyTest");
}
[TearDown]
public void RunAfterEveryTest()
{
Console.WriteLine("RunAfterEveryTest");
}
[Test]
public void Test1()
{
Console.WriteLine("Test1()");
}
[TestCase("case1")]
[TestCase("case2")]
public void Test2(string param)
{
Console.WriteLine($"Test2({param})");
}
}
The output is:
RunBeforeAnyTest
Test1()
RunAfterEveryTest
RunBeforeAnyTest
Test2(case1)
RunAfterEveryTest
RunBeforeAnyTest
Test2(case2)
RunAfterEveryTest
Isn't that what you hoped?

NUnit: how to invoke Test from another class with Parallelizable

When trying to invoke a Test from a different class from where it is implemented, it does not execute the Parallelizable attribute, instead, it only executes the methods sequentially ( Alltest_2() and Alltest_1() ). Is there any way to invoke them so that they are executed in parallel?
Here's a code sample:
public class AO_Alarms_4 : AO_Alarms_3
{
[SetUp]
public void DefaultSetUp(){ }
[Test]
public void Alltest_Clases()
{
Alltest_2();
Alltest_1();
}
[TearDown]
public void DefaultTearDown() { }
}
[TestFixture]
[Parallelizable]
public class AO_Alarms_3 : AO_Alarms_2
{
public WebDriverFactory driver = new WebDriverFactory(Utils.Browser);
[SetUp]
public void login_2()
{
//code
}
[Test]
[Parallelizable]
public void Alltest_2()
{
test_2();
}
public void test_2()
{
//code
}
[TearDown]
public void teardown_2()
{
//code
}
}
[TestFixture]
[Parallelizable]
public class AO_Alarms_2
{
public WebDriverFactory driver = new WebDriverFactory(Utils.Browser);
[SetUp]
public void login_1()
{
//code
}
[Test]
[Parallelizable]
public void Alltest_1()
{
test1_1();
test1_2();
}
[Test]
public void test1_1()
{
//code
}
[Test]
public void test1_2()
{
//code
}
[TearDown]
public void teardown_1()
{
//code
}
}
You can't simply call tests yourself and expect to get any of the normal NUnit behavior around tests. For example, NUnit knows what to do when it calls a test with [Parallelizable] on it - and what it does is fairly complicated. Your own call is simply calling the method you wrote.
There is nothing to stop you from calling common methods within a given test, but the tests themselves have to be invoked by NUnit.
If you can rephrase or ask another question about what you are actually trying to accomplish here, we can probably give you some advice about alternatives.

How to Run c# Multiple Selenium Unit Test with one driver instance?

i have a problem running Multiple C# Selenium Unit Test tests with one driver instance.
Please find my class as below.
Folder : Com.Main.Web.Selenium
SeleniumTestInitialize.cs is the main class which contains the driver.
[DeploymentItem(#"Resources\IEDriverServer.exe")]
public class SeleniumTestInitialize
{
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
private TestContext testContextInstance;
public bool SeleniumExecutionTerminateFlag=false;
public SeleniumTestInitialize seleniumTestInitalize;
public FindWebDriverElement findWebDriverElement;
public JavaScriptCalls javaScriptCalls;
public OperateOnWebDriverElement operateOnWebDriverElement;
**public RemoteWebDriver driver;**
// how to use this driver object across multiple unit test classes
public string baseURL;
public void SeleniumSetup()
{
try
{
Console.WriteLine("Starting Driver...........");
seleniumTestInitalize = new SeleniumTestInitialize();
var options = new InternetExplorerOptions
{
IntroduceInstabilityByIgnoringProtectedModeSettings = true,
//ForceCreateProcessApi=true
EnableNativeEvents = false,
RequireWindowFocus = false,
IgnoreZoomLevel = true
};
driver = new InternetExplorerDriver(TestContext.DeploymentDirectory, options);
javaScriptCalls = new JavaScriptCalls(driver);
findWebDriverElement = new FindWebDriverElement(javaScriptCalls);
operateOnWebDriverElement = new OperateOnWebDriverElement(findWebDriverElement);
GoToSite(ConfigParameters.WEB_APPLICATION_URL);
driver.Manage().Window.Maximize();
}
catch (Exception e)
{
log.Debug("Error Starting Web Driver...........");
Console.WriteLine(e.StackTrace);
}
}
public bool SeleniumInitalizeCheck()
{
if (seleniumTestInitalize != null)
return true;
else
return false;
}
public void SeleniumQuit()
{
Console.WriteLine("Quitting Driver...........");
try
{
if (driver != null)
{
driver.Quit();
}
log.Info("Closing Web Driver...........");
ProcessMgn.killProcessByNames("IEDriverServer");//Make sure the process is killed
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
public void GoToSite(string urlToOpen)
{
driver.Navigate().GoToUrl(urlToOpen);
}
}
Folder com.main.tests
Test01.cs
[TestClass]
public class Test01 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void UCP002_M1()
{
var userName = this.TestContext.DataRow["UserName"].ToString();
var passWord = this.TestContext.DataRow["PassWord"].ToString();
//use the local host adress for your project here->
baseURL = this.TestContext.DataRow["URL"].ToString();
driver.Navigate().GoToUrl(baseURL);
//driver.FindElement(By.XPath("//html/body/div[2]/div/a/p/desc")).Click();
//driver.FindElement(By.Id("registerLink")).Click();
driver.FindElement(By.Id("ctl00_LoginTextBox")).Clear();
driver.FindElement(By.Id("ctl00_LoginTextBox")).SendKeys(userName);
driver.FindElement(By.Id("ctl00_PasswordTextbox")).Clear();
driver.FindElement(By.Id("ctl00_PasswordTextbox")).SendKeys(passWord);
driver.FindElement(By.Id("ctl00_LogInButton")).Click();
}
}
Test02.cs
[TestClass]
public class Test02 : SeleniumTestInitialize
{
[TestInitialize]
public void Setup()
{
SeleniumExecutionTerminateFlag = false;
if (!SeleniumInitalizeCheck())
{
SeleniumSetup();
}
}
[TestCleanup]
public void TearDown()
{
if (SeleniumExecutionTerminateFlag)
{
SeleniumQuit();
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.TestCase", "http://tfsserver:8080/tfs/PoL;project", "1320", DataAccessMethod.Sequential)]
public void Test02()
{
//some test script
}
}
I have created an ordered test and prioritized the tests in the order of execution . But it is invoking two instances of the driver that means two times the browser.
My question is to How to share a single driver object across all selenium unit tests ?? create at the start and close the driver at the end.
Thanks.
HI If you are using using NUnit.Framework;
The code Execution plan is like below.
For First Test Case
[TestFixtureSetup] ---->For each test case this will work so here we can
initialize the driver instance.
[TestMethod] ----->test method will goes here
[TearDown] -----> clean up code
**For Second Test Case**
[TestFixtureSetup]
[TestMethod]
[TearDown]
If you have to run both test case in one browser instance
Dont close the driver inside TearDown.
AND INITIALIZE THE DRIVER UNDER TextFixtureSetup
[TestFixture()]
public class TestClass
{
[TestFixtureSetUp]
public void Init()
{
Driver.initialize(new InternetExplorerDriver());
}
[TearDown]
public void Close()
{
//dont do any driver.close()
}
[TestMethod]
public void TestCase001()
{
//your code goes here
}
[TestMethod]
public void TestCase002()
{
//your code goes here
}
You can take a look on this thread, where I answered how I did it: How to run multiple test methods in same browser instance without closing it (C#, SeleniumWebDriverz NUnit)?
Basically, I used:
using Microsoft.VisualStudio.TestTools.UnitTesting;
Instead of:
using NUnit.Framework;
So now I have next hierarchy:
[TestFixture]
[TestFixtureSetup] // this is where I initialize my WebDriver " new FirefoxDriver(); "
[Test] //first test
[Test] //second test
[Test] //third test
[TestFixtureTearDown] // this is where I close my driver
With this changes, my browser will open only once for TestFixture (or TestClass if you use "using Microsoft.VisualStudio.TestTools.UnitTesting;") and all [Test]-s from that fixture will run in that same browser instance. After all tests are done, browser will close.
Hope this will help someone else in future. Ask me if you need additional help.
I used NUnit Framework:
using NUnit.Framework;
I then set up my WebDriver initialisation, test and teardown like this:
[TestFixture()]
class NUnitSeleniumTests
{
[OneTimeSetUp]
public void Init()
{
driverIE = new InternetExplorerDriver(ConfigurationManager.AppSettings["IEDriver"]);
driverIE.Manage().Window.Maximize();
// other setup logic
}
[Test]
public void TestMethod1()
{
// Test logic
}
[Test]
public void TestMethod2()
{
// Test logic
}
...
...
...
[Test]
public void TestMethodN()
{
// Test logic
}
[OneTimeTearDown]
public void Close()
{
driverIE.Close();
}
}
When I Run All tests, the WebDriver driverIE is initialised. All tests then execute in that WebDriver instance before the WebDriver instance is closed at the end of the test run.
The tests execute in alphabetical order by default; each test can also execute in isolation.

Categories

Resources