Using Selenium C# web driver with NUnit for automation. I am generating Allure report using command line and my report gets fantastically created but I need help on the following issue:
I have the following structure using Page object model (2 Test and 1 Page). Now when I see the report it shows at the top Test run (2 testsuites, 2 testcases) and each testcase is a testsuite. I want it to say 1 testsuites, 2 testcases. How do I do that?
namespace ApplicationName.TestCases
{
[TestFixture]
class VerifyCreateOrder
{
IWebDriver driver;
[SetUp]
public void Initialize()
{
driver = new FirefoxDriver();
}
[TestCase]
public void doCreateOrder()
{
LoginPage loginPage = new LoginPage();
//some Assertion
}
}
}
namespace ApplicationName.TestCases
{
[TestFixture]
class SearchOrder
{
IWebDriver driver;
[SetUp]
public void Initialize()
{
driver = new FirefoxDriver();
}
[TestCase]
public void doSearchOrder()
{
LoginPage loginPage = new LoginPage();
//some Assertion
}
}
}
The below is my LoginPage Page object:
namespace ApplicationName.Pages
{
class LoginPage
{
public void doLogin(IWebDriver driver, String username, String password)
{
driver.Navigate().GoToUrl("http://www.myxyzsite.com");
driver.FindElement(By.Id("xyz")).SendKeys(username);
driver.FindElement(By.Id("xyz")).SendKeys(password);
driver.FindElement(By.Id("xyz")).Click();
}
}
}
I read about the NUnit suite attribute at http://www.nunit.org/index.php?p=suite&r=2.5.5 and created a c# class with enumerator as described but how do i call it/wire it? What changes do I need to make for my test classes?
namespace NUnit.Tests
{
public class MyTestSuite
{
[Suite]
public static IEnumerable Suite
{
get
{
ArrayList suite = new ArrayList();
suite.Add(new VerifyCreateOrder());
suite.Add(new SearchOrder());
return suite;
}
}
}
}
I want it to say 1 testsuites, 2 testcases. How do I do that?
Without adding a Suite or similar, you could put both Test cases into the same TestFixture, since that's what the testsuite output is built from. You may be able to do that using a partial class, or you can simply conflate the two classes. However, your Suite solution is a better choice.
What changes do I need to make for my test classes?
Call NUnit with the option /fixture:NUnit.Tests.MyTestSuite.
Note that all of this has changed with NUnit 3 and the Suite attribute is gone. I can't see any way to do what you want in NUnit 3 short of reorganizing your test cases.
If it's very important to merge tests into suites, you can use XSLT. The NUnit test result schema is quite straightforward and easy to manipulate using XSLT.
Related
Lets say i have to open google in 2 browsers, search Test1 in 1st, search Test 2 in 2nd. It opens 2 browsers, writes Test1Test2 in one browser and pass the test. how do i get around it?
it works well if i declare driver in every test function, but this cannot be done if i want to use RemoteWebDriver later to run it on different machines.(because it then uses only one node and doesn't do anything on other) Heard about using non static browser as well, but not sure how to use it, and not sure if that is solution of the problem?
namespace ParallelGrid
{
[TestFixture]
[Parallelizable]
public class ParallelGrid1
{
[ThreadStatic]
public static IWebDriver driver;
[SetUp]
public void Setup()
{
ChromeOptions options = new ChromeOptions();
driver = new ChromeDriver();
// driver = new RemoteWebDriver(new Uri("http://xxx.xxx.xx.xxx:4444/wd/hub"), options.ToCapabilities(), TimeSpan.FromSeconds(600));//hub id goes here
}
[Test]
[Parallelizable]
public void Test1()
{
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.Name("q")).Click();
driver.FindElement(By.Name("q")).SendKeys("Test");
}
[Test]
[Parallelizable]
public void Test2()
{
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.Name("q")).Click();
driver.FindElement(By.Name("q")).SendKeys("Grid");
}
}
}
For parallelization to work with NUnit and C# you can only parallelize on Test class at a time. So you have to have one test per class.
https://github.com/nunit/nunit/issues/2252
I'm trying to run the same nunit Test method with different values in parallel. However the second test seems to fail (i think it's trying to use the first instance of the browser;
This is the test;
namespace AutomationProject.Login_Test_Cases
{
[TestFixture]
[Parallelizable(ParallelScope.Children)]
class Login_Test_Cases: BaseTest
{
[Test]
public void LoginPar([Values("skynet" ,"skynet2")] string username)
{
lg.Log_In(username, "password");
}
}
}
This is the baseTest where the browser is set up;
namespace AutomationProject.BaseClasses
{
public class BaseTest
{
public Log_In_Methods lg;
public IWebDriver driver;
[SetUp]
public void StartBrowser()
{
System.Diagnostics.Trace.AutoFlush = true;
ChromeOptions options = new ChromeOptions();
options.AddAdditionalCapability("useAutomationExtension", false);
driver = new ChromeDriver(//path to chrome driver);
lg = new Log_In_Methods(driver);
driver.Manage().Window.Maximize();
driver.Url = "http://login-test.com";
}
I've also added [assembly: Parallelizable(ParallelScope.Children)]
[assembly: LevelOfParallelism(2)] to AssemblyInfo
The second test always seems to fail (the browser does not even get the url)
I can run different classes and tests in parallel with no issues.
Does anyone know if it's possible to run the same test method in parallel with different values?
Does anyone know if it's possible to run the same test method in parallel with different values?
This is absolutely possible. The issue here is that both tests run in parallel on a single instance of the BaseTest class, and thus you only have a lg field which both tests are trying to create/use simultaneously.
Being able to run the two separate tests with two separate BaseTest objects is an open feature request, see here: https://github.com/nunit/nunit/issues/2574
In the meantime, if you were to include your [SetUp] logic within your test method and use local variables, what you're trying to do should work.
I want to take screenshot of a failed test case. But I don't know how to force Nunit to use my listener.
I was trying to use IAddins, but Nunit doesn't have NUnit.Core.Extensibility lib.
My code:
using System;
using OpenQA.Selenium;
using NUnit.Framework.Interfaces;
using AT_MentoringPortal.Driver;
using System.Drawing.Imaging;
namespace AT_MentoringPortal.listeners
{
public class ScreenshotListener : ITestListener
{
private readonly string path = ".//screens//";
public void TestFinished(ITestResult result)
{
if (result.ResultState.Status == TestStatus.Failed)
{
IWebDriver driver = DriverFactory.GetDriver();
this.MakeScreenshot(driver, result.Name);
}
}
public void MakeScreenshot(IWebDriver driver, string testName)
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd-hhmm-ss");
var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
screenshot.SaveAsFile($"{this.path}{timestamp} {testName}", ImageFormat.Jpeg);
}
public void TestOutput(TestOutput output)
{
// throw new NotImplementedException();
}
public void TestStarted(ITest test)
{
// throw new NotImplementedException();
}
}
}
Please, show me how to start my listener in test class.
ITestListener is an internal interface used by NUnit itself in running tests. There was a similar interface in NUnit V2 (TestListener) and you were able to create addins that used it. NUnit 3 doesn't have addins in the way that NUnit 2 did, although it can be extended in other ways.
Did you want to save a screen shot for only certain tests? Or for each test in a certain fixture? Or more generally?
To do it within a fixture, you could use a OneTimeTearDown method.
I am using XUnit with TestDriven.Net or Resharper test runner to execute my tests. I really like the BDD style of writing my tests so I was wondering if there is some what that we can modify the output of these frameworks?
I like to name my test with underscores and want to split the test name and format it in Given, When, Then format. Is it at all possible with these tools?
I'm not sure what you try to do. It seems that you want to change test names displayed on a certain test runnder. Displaying test names are actually depended on just test runner(tool). This means that we could customize names or couldn't by which test runner we use.
Checked out the following code, which could be the code that you want to do. If the code is not the case, at least, I think that it can show you some idea about how to customize test names.
public class Given_Foo
{
[Test]
public void Then_Bar_returns_correct_result()
{
Assert.True(flase, "Check out test names...");
}
}
public class TestAttribute : FactAttribute
{
public TestAttribute()
{
}
protected override IEnumerable<ITestCommand> EnumerateTestCommands(IMethodInfo method)
{
yield return new CustomNamedTestCommand(method);
}
}
public class CustomNamedTestCommand : FactCommand
{
public CustomNamedTestCommand(IMethodInfo method) : base(method)
{
this.DisplayName = DisplayName.Replace("_", " ");
}
}
I am new to automation testing and selenium and have been watching alot of selenium tutorials. I realized that selenium test cases are written in 2 formats and im not sure which one to go with.
1)
namespace SeleniumTests
{
[TestFixture]
public class Login
{
private IWebDriver driver;
private StringBuilder verificationErrors;
private string baseURL;
private bool acceptNextAlert = true;
[SetUp]
public void SetupTest()
{
driver = new FirefoxDriver();
baseURL = "http://chapters.com";
verificationErrors = new StringBuilder();
}
[TearDown]
public void TeardownTest()
{
try
{
driver.Quit();
}
catch (Exception)
{
// Ignore errors if unable to close the browser
}
Assert.AreEqual("", verificationErrors.ToString());
}
[Test]
public void TheLoginTest()
{
driver.Navigate().GoToUrl(baseURL");
driver.FindElement(By.Id("loginCtrl_UserName")).Clear();
driver.FindElement(By.Id("loginCtrl_UserName")).SendKeys("operations");
driver.FindElement(By.Id("loginCtrl_Password")).Clear();
driver.FindElement(By.Id("loginCtrl_Password")).SendKeys("welcome");
driver.FindElement(By.Id("loginCtrl_LoginButton")).Click();
driver.FindElement(By.Id("btnInitialLoad")).Click();
Assert.AreEqual("Chapters", driver.Title);
}
}
}
2)
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
namespace TestProject1
{
public class UnitTest1
{
public void main()
{
FirefoxDriver driver = new FirefoxDriver();
string baseURL = "http://seleniumhq.org/";
driver.Navigate().GoToUrl(baseURL);
driver.FindElement(By.LinkText("Projects")).Click();
driver.FindElement(By.LinkText("Selenium IDE")).Click();
Assert.AreEqual(driver.FindElement(By.XPath("//div[#id='mainContent']/table/tbody/tr/td/p/b")).Text, "Selenium IDE");
driver.Close();
}
}
}
Which one do I go with?
Thanks
The second scenario is simple sequential flow of statements without added advantage of any frameworks like Junit,TestNG,Nunit. It is good for people who have just started with Selenium 2.0 and want to practice with different methods provided by webdriver.
The first scenario is logical division of the code into different annotations provided by Nunit, with these annotations one can get tremendous power of the underlining framework being used, in your case Nunit, these annotation are automatically called by the Nunit framework in a defined order. Apart from this there are multliple other functionalities provided by these frameworks like Reporting,Assertions,Support for Mock Objects,etc
Always use the first scenario for writing Selenium code because along with understanding of the webdriver code, one also gets hang of the underlining framework.