c# nunit extent reports not getting screenshot, passing on exception - c#

i am trying to add screenshot to my extent report.
I have applied exception to one of my test methods, and giving screenshot taking in exception.
Then i have called the screenshot function in teardown, so screenshot can show up in case it is failed. All good. but when i run the code that should be failing, it marks it pass due to exception, and in extent report it displays it as pass.How do i make it appear fail in extent report and display the fail screenshot with it?
namespace CreateTeamSpeed
{
class ReportsGenerationClass
{
protected ExtentReports extent;
protected ExtentTest test;
[OneTimeSetUp]
protected void Setup()
{
string path = TestContext.CurrentContext.TestDirectory + "\\";
string fileName = this.GetType().ToString() + "report.html";
var htmlReporter = new ExtentHtmlReporter(path + fileName);
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
}
[SetUp]
public void BeforeTest()
{
test = extent.CreateTest(TestContext.CurrentContext.Test.Name);
}
[TearDown]
public void AfterTest()
{
var status = TestContext.CurrentContext.Result.Outcome.Status;
var stacktrace = string.IsNullOrEmpty(TestContext.CurrentContext.Result.StackTrace) ? "" : string.Format("{0}", TestContext.CurrentContext.Result.StackTrace);
Status logstatus;
switch (status)
{
case TestStatus.Failed:
logstatus = Status.Fail;
test.AddScreenCaptureFromPath("screenshot.png");
break;
case TestStatus.Inconclusive:
logstatus = Status.Warning;
break;
case TestStatus.Skipped:
logstatus = Status.Skip;
break;
default:
logstatus = Status.Pass;
break;
}
var mediaModel = MediaEntityBuilder.CreateScreenCaptureFromPath("screenshot.png").Build();
test.Log(logstatus, "Test ended with " + logstatus + stacktrace + mediaModel);
extent.Flush();
}
[Test]
public void Test1()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("start-maximized");
IWebDriver driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.Name("q")).SendKeys("Test");
driver.FindElement(By.Name("btnK")).SendKeys(Keys.Enter);
driver.Quit();
}
[Test]
public void Test2()
{
ChromeOptions options = new ChromeOptions();
options.AddArgument("start-maximized");
IWebDriver driver = new ChromeDriver(options);
try{
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.Name("qt")).SendKeys("Test");
driver.FindElement(By.Name("btnK")).SendKeys(Keys.Enter);
driver.Quit();
}
catch (Exception ex)
{
((ITakesScreenshot)driver).GetScreenshot().SaveAsFile("screenshot.png", ScreenshotImageFormat.Png);
}
}
}
}'''

If you handle exception, it does not fail test.
To make it fail for external running tools, you can add call of Assert.Fail(); after screenshot.

Related

Selenium webdriver C# checking for text

Trying to write a test that checks if some words are on the page.
I'm getting a no such element: Unable to locate element: {"method":"xpath","selector":"//*[#id='webform - submission - questionnaire - form - ajax']/section[2]"} message and the test for textIsOnThePage fails, everything else passes. Haven't used C# for a long time and trying out testing for the first time, what am I missing with textIsOnThePage ? This is the Xpath that the browser gives me.
public class Tests
{
IWebDriver driver;
String test_url = "http://mytesturl.com";
private readonly Random _random = new Random();
public void start_browser()
{
driver = new EdgeDriver(#"C:\Users\ADMIN\Downloads\edgedriver_win64");
driver.Manage().Window.Maximize();
}
//I run some tests on the page
public void test_page()
{
driver.Url = test_url;
driver.Navigate().GoToUrl("http://mytesturl.com");
Thread.Sleep(5000);
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
try {IWebElement sButton2 = driver.FindElement(By.XPath("//button[#class='agree-button eu-cookie-compliance-secondary-button']"));
js.ExecuteScript("arguments[0].click()", sButton2);
} catch (Exception) { }
for (int a = 0; a < 10; a++)
{
Thread.Sleep(2500);
//I call out my method
TextIsOnThePage("weigh", "weight");
Thread.Sleep(2500);
}
private void TextIsOnThePage(string textToFind, string warning)
{
driver.Url = test_url;
driver.Navigate().GoToUrl("http://mytesturl.com");
Thread.Sleep(5000);
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
var element = driver.FindElement(By.XPath("//*[#id='webform - submission - questionnaire - form - ajax']/section[2]"));
if (!string.IsNullOrEmpty(element.Text) && element.Text.Contains(textToFind))
{
Console.WriteLine("Text for " + warning + "is present");
}
else
{
Console.WriteLine(warning + " test failed");
}
}
public void close_Browser()
{
driver.Quit();
}
}

There are no "CreateDevToolsSession" in ChromeDriver Selenium

I'm using Selenium and trying to use CDP to mock Geolocation. But I'm having a problem that the ChromeDriver dont have anything like CreateDevToolsSession.
This is the code that I've found in the Selenium Documentation:
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.DevTools.V87.Emulation;
namespace dotnet_test {
class Program {
public static void Main(string[] args) {
GeoLocation().GetAwaiter().GetResult();
}
public static async Task GeoLocation() {
ChromeDriver driver = new ChromeDriver();
DevToolsSession devToolsSession = driver.CreateDevToolsSession();
var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings();
geoLocationOverrideCommandSettings.Latitude = 51.507351;
geoLocationOverrideCommandSettings.Longitude = -0.127758;
geoLocationOverrideCommandSettings.Accuracy = 1;
await devToolsSession
.GetVersionSpecificDomains<OpenQA.Selenium.DevTools.V87.DevToolsSessionDomains>()
.Emulation
.SetGeolocationOverride(geoLocationOverrideCommandSettings);
driver.Url = "<your site url>";
}
}
}
Thanks.
** UPDATE 1 **
This is the link for the documentation references.
https://www.selenium.dev/documentation/webdriver/bidirectional/chrome_devtools/
Selenium 4 Breaking Changes
CreateDevToolsSession() has been replaced with GetDevToolsSession().
A lot of examples you find online were written with the Beta version, like this one: https://dotjord.wordpress.com/2020/09/13/how-to-capture-network-activity-with-selenium-4-in-asp-net-core-3-1/ and this old code gets copied around https://stackoverflow.com/a/69478097/495455
Beta (old code):
IDevTools devTools = driver as IDevTools;
DevToolsSession session = devTools.CreateDevToolsSession();
session.Network.ResponseReceived += ResponseReceivedHandler;
session.Network.Enable(new EnableCommandSettings());
driver.Navigate().GoToUrl(url);
public void ResponseReceivedHandler(object sender, ResponseReceivedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"Status: { e.Response.Status } : {e.Response.StatusText} | File: { e.Response.MimeType } | Url: { e.Response.Url }");
}
Alpha (working code):
using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V96.DevToolsSessionDomains;
var driver = new ChromeDriver();
var devTools = (IDevTools)driver;
IDevToolsSession session = devTools.GetDevToolsSession();
var domains = session.GetVersionSpecificDomains<DevToolsSessionDomains>();
domains.Network.ResponseReceived += ResponseReceivedHandler;
await domains.Network.Enable(new OpenQA.Selenium.DevTools.V96.Network.EnableCommandSettings());
driver.Navigate().GoToUrl(url);
void ResponseReceivedHandler(object sender, ResponseReceivedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"Status: { e.Response.Status } : {e.Response.StatusText} | File: { e.Response.MimeType } | Url: { e.Response.Url }");
}
In a addition to the nice answer from Jeremy Thompson, I wanted to share a new approach without being version and browser specific for Selenium 4+. (Works in Chrome and Edge with Selenium 4.8)
public void SetupNetworkLogging(IWebDriver driver)
{
NetworkManager manager = new NetworkManager(driver);
manager.NetworkResponseReceived += ResponseHandler;
manager.StartMonitoring();
}
private void ResponseHandler(object sender, NetworkResponseReceivedEventArgs e)
{
Console.WriteLine($"Http status: {e.ResponseStatusCode} : {e.ResponseBody} | Url: {e.ResponseUrl} ");
}
The official documentation for geolocation is now updated, for geolocation it seems to be nessessary, but if you don't need to specify a version use that:
IDevTools devTools = driver as IDevTools;
var session = devTools.GetDevToolsSession();
Offical documentation can be found here.

What should I change so that Chrome not opens New Window every time when this code triggers

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
using System.IO;
using System.Threading;
namespace TallyWhatsappsender
{
public class Class1
{
OpenQA.Selenium.IWebDriver chrome_driver = null;
public String InitProcess(String contact,String file_route,String title,String chrome_binary)
{
try
{
if (!System.IO.File.Exists(file_route))
{
return "Error : Attachment not found!";
}
if (!System.IO.File.Exists(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "chromedriver.exe")))
{
return "Error : Chromedriver.exe executable not found!\n chromedriver.exe file is missing\n update or reinstalling may fix the problem";
}
var chrome_driver_service = ChromeDriverService.CreateDefaultService(AppDomain.CurrentDomain.BaseDirectory, "chromedriver.exe");
chrome_driver_service.HideCommandPromptWindow = true;
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.UnhandledPromptBehavior = UnhandledPromptBehavior.Accept;
if (File.Exists(chrome_binary))
{
chromeOptions.BinaryLocation = chrome_binary;
}
chrome_driver = new ChromeDriver(chrome_driver_service, chromeOptions);
IJavaScriptExecutor javaScriptExecutor = (IJavaScriptExecutor)chrome_driver;
foreach (string ct in contact.Split(','))
{
if (string.IsNullOrEmpty(ct.Trim()))
{
break;
}
if(ct.Trim().Length != 12)
{
if (!(chrome_driver is null)) chrome_driver.Quit();
return "Error : Invalid contact number-" + ct;
}
chrome_driver.Url = "https://web.whatsapp.com/send?phone=" + ct.Trim();
try
{
chrome_driver.SwitchTo().Alert().Accept();
}
catch (NoAlertPresentException e1)
{
Console.WriteLine(e1.Message);
}
try
{
WebDriverWait wait = new WebDriverWait(chrome_driver, System.TimeSpan.FromSeconds(60));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath("//*[#id='main']/footer/div[1]/div[2]/div/div[2]")));
}
catch (WebDriverTimeoutException)
{
continue;
}
//sending file
IWebElement file_open = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[1]/div[2]/div/div/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", file_open);
chrome_driver.FindElement(By.CssSelector("input[type='file']")).SendKeys(file_route);
WebDriverWait wait2 = new WebDriverWait(chrome_driver, System.TimeSpan.FromSeconds(30));
wait2.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath("//*[#id='app']/div/div/div[2]/div[2]/span/div/span/div/div/div[2]/span/div/div/span")));
IWebElement file_send = chrome_driver.FindElement(By.XPath("//*[#id='app']/div/div/div[2]/div[2]/span/div/span/div/div/div[2]/span/div/div/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", file_send);
Thread.Sleep(1000);
//sending text
IWebElement typebox = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[2]/div/div[2]"));//:chrome_driver.FindElements(By.CssSelector("div[class ='_3u328 copyable-text selectable-text']"))[0];
typebox.SendKeys(title);
IWebElement text_send = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[3]/button/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", text_send);
Thread.Sleep(3000);
}
//chrome_driver.Quit();
return "Process finished";
}
//catch (Exception ex)
//{
// if (!(chrome_driver is null)) chrome_driver.Quit();
// return ex.Message;
//}
}
}
}
I am using the above code for exporting a PDF file from tally and send it through Whatsapp Automatically.
I am facing a problem :
Every time I use this option a new tab of chrome opens and closes after sending file, because of new window it asks me to login to whatsapp every time , I think it will sort out if it do not close after sending file or when I activate it , it goes automatically to the previously opened Web.Whatsapp.com so that I will not need authentication each time.
please help me out into this .
Thanks in advance
Every time you call chrome_driver = new ChromeDriver(chrome_driver_service, chromeOptions); a new tab opens.
Try separating the initiating process and the sending process.
For example, your InitProcess method could look like the following:
public InitProcess(String chrome_binary)
{
try
{
if (!System.IO.File.Exists(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "chromedriver.exe")))
{
return "Error : Chromedriver.exe executable not found!\n chromedriver.exe file is missing\n update or reinstalling may fix the problem";
}
var chrome_driver_service = ChromeDriverService.CreateDefaultService(AppDomain.CurrentDomain.BaseDirectory, "chromedriver.exe");
chrome_driver_service.HideCommandPromptWindow = true;
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.UnhandledPromptBehavior = UnhandledPromptBehavior.Accept;
if (File.Exists(chrome_binary))
{
chromeOptions.BinaryLocation = chrome_binary;
}
chrome_driver = new ChromeDriver(chrome_driver_service, chromeOptions);
return "Intiated";
}
}
And then you could add a Send function:
public String Send(String contact, String file_route, String title)
{
try
{
IJavaScriptExecutor javaScriptExecutor = (IJavaScriptExecutor)chrome_driver;
foreach (string ct in contact.Split(','))
{
if (string.IsNullOrEmpty(ct.Trim()))
{
break;
}
if(ct.Trim().Length != 12)
{
if (!(chrome_driver is null)) chrome_driver.Quit();
return "Error : Invalid contact number-" + ct;
}
chrome_driver.Url = "https://web.whatsapp.com/send?phone=" + ct.Trim();
try
{
chrome_driver.SwitchTo().Alert().Accept();
}
catch (NoAlertPresentException e1)
{
Console.WriteLine(e1.Message);
}
try
{
WebDriverWait wait = new WebDriverWait(chrome_driver, System.TimeSpan.FromSeconds(60));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath("//*[#id='main']/footer/div[1]/div[2]/div/div[2]")));
}
catch (WebDriverTimeoutException)
{
continue;
}
//sending file
IWebElement file_open = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[1]/div[2]/div/div/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", file_open);
chrome_driver.FindElement(By.CssSelector("input[type='file']")).SendKeys(file_route);
WebDriverWait wait2 = new WebDriverWait(chrome_driver, System.TimeSpan.FromSeconds(30));
wait2.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.XPath("//*[#id='app']/div/div/div[2]/div[2]/span/div/span/div/div/div[2]/span/div/div/span")));
IWebElement file_send = chrome_driver.FindElement(By.XPath("//*[#id='app']/div/div/div[2]/div[2]/span/div/span/div/div/div[2]/span/div/div/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", file_send);
Thread.Sleep(1000);
//sending text
IWebElement typebox = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[2]/div/div[2]"));//:chrome_driver.FindElements(By.CssSelector("div[class ='_3u328 copyable-text selectable-text']"))[0];
typebox.SendKeys(title);
IWebElement text_send = chrome_driver.FindElement(By.XPath("//*[#id='main']/footer/div[1]/div[3]/button/span"));
javaScriptExecutor.ExecuteScript("arguments[0].click();", text_send);
Thread.Sleep(3000);
return "Process finished";
}
}
}
Now you call InitProcess only once at the beginning of you program and Send every time you want to send the file.

Compile results from all test suites in extent report

The extent report is only reporting the last test suite that has been run.
I have set up selenium tests with 10 different suits that is run in order. The problem is that the Extent Report is only logging the results of the last suite. I have tried different ways of implementing the report to compile all of the results.
The code structure:
BaseSetUp Class - initialze the driver (OneTimeSetUp, SetUp, TearDown, OnetimeTearDown)
Generalmethod calls - inherits from BaseSetUp
PageObject Page - get all Page Objects
TestSuits - Inherits from General methods.
I have the report in the BaseSetUp class like this:
[OneTimeSetUp]
public void Setup()
{
try
{
extent = new ExtentReports();
var dir = AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin\\Debug", "");
var htmlReporter = new ExtentHtmlReporter(dir + "\\Test_Execution_Reports" + "\\Automation_Report" + ".html");
extent.AddSystemInfo("Environment", "Xylect AT");
extent.AddSystemInfo("User Name", "Lucas");
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
}
catch (Exception e)
{
throw (e);
}}
[SetUp]
public void BeforeTest()
{
try
{
_test = extent.CreateTest(TestContext.CurrentContext.Test.Name);
}
catch (Exception e)
{
throw (e);
}
}
[TearDown]
public void AfterTest()
{
try
{
var status = TestContext.CurrentContext.Result.Outcome.Status;
var stacktrace = "" + TestContext.CurrentContext.Result.StackTrace + "";
var errorMessage = TestContext.CurrentContext.Result.Message;
Status logstatus;
switch (status)
{
case TestStatus.Failed:
logstatus = Status.Fail;
string screenShotPath = Capture(driver, TestContext.CurrentContext.Test.Name);
_test.Log(logstatus, "Test ended with " + logstatus + " – " + errorMessage);
_test.Log(logstatus, "Snapshot below: " + _test.AddScreenCaptureFromPath(screenShotPath));
break;
case TestStatus.Skipped:
logstatus = Status.Skip;
_test.Log(logstatus, "Test ended with " + logstatus);
break;
default:
logstatus = Status.Pass;
_test.Log(logstatus, "Test ended with " + logstatus);
break;
}
}
catch (Exception e)
{
throw (e);
}
}
[OneTimeTearDown]
public void TearDown()
{
try
{
//zip();
//Email();
extent.Flush();
driver.Close();
driver.Quit();
}
catch (Exception e)
{
throw (e);
}
}
Ive seen a couple of methods where the prevous report is added to the "new" created one, but i did not get this to work.
Example of a testcase in one of the testsuites
[TestCase(TestName = "01_LogIn"), Order(1)]
public void LogIn()
{
LogIn();
string loginAssert = HomePage.expLoginName.Text;
Assert.IsTrue(loginAssert.Contains("Hi, " + username + ""), "Login falied");
}
Any ideas on how i should move forward?
Running extent report V4
You just follow this link. I hope it solves your problem.
You must create 3 classes.
BaseFixture.cs
ExtentManager.cs
ExtentTestManager.cs
After that, you can initialize the BaseFixture in every test class.
[TestFixture, Parallelizable(ParallelScope.Fixtures)]
public class MemberLogInOut : BaseFixture
https://github.com/anshooarora/extentreports-csharp/tree/master/ExtentReports/ExtentReports.Tests/Parallel

Timeout in Selenium Chrome driver

I have a code which triggers 5 console apps (same code base different location).
public static void RunLoadGenInstances(int loadGenInstanceCount, string exePath)
{
try
{
for (int i = 1; i < loadGenInstanceCount; i++)
{
Thread.Sleep(1000);
Process.Start(exePath + i + #"\bin\Debug\wm_uk_hr_loadgen.exe");
Thread.Sleep(1000);
}
}
catch (Exception ex)
{
}
}
Each of the exe inilitializes the ChromeDriver.exe from their own executable path and opens up Chrome.
ChromeOptions options = new ChromeOptions();
options.AddUserProfilePreference("download.default_directory", file_path);
options.AddUserProfilePreference("disable-popup-blocking", "true");
options.AddArguments("--disable-extensions");
options.AddArguments("--start-maximized");
ChromeDriverService service = ChromeDriverService.CreateDefaultService(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
service.SuppressInitialDiagnosticInformation = true;
service.HideCommandPromptWindow = true;
string url = HRSSUrl;
chromeDriver = new ChromeDriver(service, options);
Thread.Sleep(500);
chromeDriver.Navigate().GoToUrl(url);
Console.WriteLine("Enter uid");
IWebElement idWait = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("__control0-user")));
IWebElement id = chromeDriver.FindElement(By.Id("__control0-user"));
id.SendKeys(c4cUserId);
Console.WriteLine("uid entered");
Console.WriteLine("Enter pwd");
IWebElement passWait = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("__control0-pass")));
IWebElement pass = chromeDriver.FindElement(By.Id("__control0-pass"));
pass.SendKeys(c4cPassword);
Console.WriteLine("pwd entered");
Console.WriteLine("click login");
IWebElement loginWait = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("__control0-logonBtn")));
IWebElement login = chromeDriver.FindElement(By.Id("__control0-logonBtn"));
login.Click();
Problem is- Chrome is able to launch and navigate to URL but it is stuck on Sign In page. This happens in 4 console apps except 1, which runs fine. Below is the exception message which I get from the failed apps.
Enter uid
at OpenQA.Selenium.Support.UI.DefaultWait`1.ThrowTimeoutException(String exce
ptionMessage, Exception lastException)
at OpenQA.Selenium.Support.UI.DefaultWait`1.Until[TResult](Func`2 condition)
at wm_uk_hr_loadgen.Program.SelectAuthenticationDropDown() in c:\UK-HR\LoadGe
n-MultiInstance\LoadGen1\Program.cs:line 273
at wm_uk_hr_loadgen.Program.Main(String[] args) in c:\UK-HR\LoadGen-MultiInst
ance\LoadGen1\Program.cs:line 105
Any help? Please let me know if any details needed.
Thanks,
Souvik

Categories