Confusion over Page Object Model C# Selenium - c#

I've written basic code which goes to a specific URL then changes the country and currency. I now want to tidy my code up and make it easier to maintain.
I've not used page object model before so have been reading about it. I understand the basic concepts of creating another class within the project and creating an extension to page objects that are used to initialize the web elements.
So essentially all my FindElements will be stored in a separate class. I've created two Classes within a PageObjects folder. HomePage and PreferencePage.
Below code is working and does exactly as I expect.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Interactions;
using System.Threading;
namespace Exercise1
{
class Program
{
static void Main(string[] args)
{
IWebDriver webDriver = new ChromeDriver();
webDriver.Navigate().GoToUrl("http://www.asos.com/men/");
webDriver.Manage().Window.Maximize();
webDriver.FindElement(By.XPath(".//button[#data-testid='country-selector-btn']")).Click();
WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(5));
IWebElement country = wait.Until(ExpectedConditions.ElementExists(By.Id("country")));
SelectElementFromDropDown(country, "India");
IWebElement currency = wait.Until(ExpectedConditions.ElementExists(By.Id("currency")));
SelectElementFromDropDown(currency, "$ USD");
webDriver.FindElement(By.XPath(".//button[#data-testid='save-country-button']")).Click();
webDriver.Quit();
}
private static void SelectElementFromDropDown(IWebElement ele, string text)
{
SelectElement select = new SelectElement(ele);
select.SelectByText(text);
}
}
}
Now I want to implement Page Object Model. I have created my main TestClass, along with a HomePage and PreferencePage class. I'm unsure of how to implement the next bit. I know my TestClass will be making a call to the HomePage for the URL and PreferencePage for the country and currency but I'm unsure how the implementation would look.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace Exercise1
{
class TestClass
{
private IWebDriver driver;
public void SetUp()
{
IWebDriver webDriver = new ChromeDriver();
webDriver.Manage().Window.Maximize();
}
public void ChangePreferences()
{
Homepage home = new Homepage(driver);
home.goToPage();
PreferencePage preference = home.GoToPreferencePage();
UpdateCountry = preference.UpdateCountryPreference();
UpdateCurrency = preference.UpdateCurrencyPreference();
UpdatePreference = preference.PreferenceUpdated();
}
}
}
HomePage class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exercise1
{
class HomePage
{
private IWebDriver driver;
public HomePage(IWebDriver driver)
{
this.driver = driver;
PageFactory.InitElements(driver, this);
}
public void goToPage()
{
driver.Navigate().GoToUrl("http://www.asos.com/men/");
}
}
}
Preference page
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exercise1.PageObjects
{
class PreferencePage
{
private IWebDriver driver;
public UpdateCountry(string text)
{
WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(5));
IWebElement country = wait.Until(ExpectedConditions.ElementExists(By.Id("country")));
SelectElementFromDropDown(country, "India");
}
public void UpdateCurrency()
{
IWebElement currency = wait.Until(ExpectedConditions.ElementExists(By.Id("currency")));
SelectElementFromDropDown(currency, "$ USD");
}
public void ClickPreference()
{
webDriver.FindElement(By.XPath(".//button[#data-testid='save-country-button']")).Click();
}
}
}

it would look like that:
class TestClass
{
private IWebDriver driver;
public void SetUp()
{
..
}
public TestChangePreferences()
{
//actual test
ChangePreferences();
}
public void ChangePreferences()
{
.......
}
}
I'd wrap it with a testing framework such as NUnit for better test management and tools.
this could give you a pretty good example:
https://github.com/nunit/nunit-csharp-samples/blob/master/DataDrivenTests/GenericTestFixture.cs

Related

Test Executed successfully but report doesn't extent report doesn't generate in specflow

Currently I am working designing my project in Specflow. I want to implement some reporting to my project. Currently I have created one separate .cs file and kept all my report setting. But when i execute my code test run successfully but report doesn't generate. i am using the given code please check and suggest me
SeleniumDriver.cs
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ReportDemoPOC
{
class SeleniumDriver
{
public static IWebDriver WebDriver { get; set; }
public static string BaseAddress
{
get { return Constants.Url; }
}
public static void Intitialize()
{
WebDriver = new ChromeDriver();
WebDriver.Manage().Window.Maximize();
TurnOnWait();
}
public static void Navigate()
{
WebDriver.Navigate().GoToUrl(BaseAddress);
}
public static void Close()
{
WebDriver.Close();
}
public static void Quit()
{
WebDriver.Quit();
}
private static void TurnOnWait()
{
WebDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
WebDriver.Manage().Timeouts().PageLoad = TimeSpan.FromMinutes(2);
}
public void Shutdown()
{
WebDriver.Quit();
}
}
}
Start.cs
using AventStack.ExtentReports;
using AventStack.ExtentReports.Reporter;
using AventStack.ExtentReports.Reporter.Configuration;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
namespace ReportDemoPOC
{
public class Start
{
public static ExtentReports extent;
public static ExtentHtmlReporter htmlReporter;
public static ExtentTest test;
static Start()
{
if (extent == null)
{
BasicSetUp();
}
}
[BeforeScenario]
public void Setup()
{
SeleniumDriver.Intitialize();
SeleniumDriver.Navigate();
test = extent.CreateTest(ScenarioContext.Current.ScenarioInfo.Title);
}
[AfterScenario]
public void TearDown()
{
if (ScenarioContext.Current.TestError != null)
{
var error = ScenarioContext.Current.TestError;
var errormessage = "<pre>" + error.Message + "</pre>";
//Add capture screen shot line here
extent.AddTestRunnerLogs(errormessage);
test.Log(Status.Error, errormessage);
test.Fail(errormessage);
}
SeleniumDriver.Close();
}
[OneTimeSetUp]
public static void BasicSetUp()
{
string pth = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
// string pth = System.IO.Directory.GetCurrentDirectory();
string actualPath = pth.Substring(0, pth.LastIndexOf("bin"));
string projectPath = new Uri(actualPath).LocalPath;
Console.WriteLine(" -----------Project Path--------------------------------------");
Console.WriteLine(projectPath);
// string reportPath = projectPath + "Reports\\" + FeatureContext.Current.FeatureInfo.Title + ".html";
string reportPath = projectPath + "Reports\\TestRunReport.html";
// Console.WriteLine("Report Path is " + reportPath);
htmlReporter = new ExtentHtmlReporter(reportPath);
htmlReporter.Configuration().Theme = Theme.Dark;
htmlReporter.Configuration().DocumentTitle = "SpecFlow Test Resport Document";
htmlReporter.Configuration().ReportName = "Feature Run Results";
extent = new ExtentReports();
extent.AttachReporter(htmlReporter);
//extent.LoadConfig(projectPath + "Extent-Config.xml");
}
[AfterFeature()]
public static void EndReport()
{
extent.Flush();
}
}
}
LoginSteps.cs
using NUnit.Framework;
using ReportDemoPOC.Page;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
namespace ReportDemoPOC.Steps
{
[Binding]
[TestFixture]
class LoginSteps : Start
{
LoginPage loginPage;
[Given(#"I am at Facebook login page")]
public void GivenIAmAtFacebookLoginPage()
{
//Navigate();
loginPage = new LoginPage();
}
[When(#"I enter ashusoni(.*)#gmail\.com in the Email or Phone textbox")]
public void WhenIEnterAshusoniGmail_ComInTheEmailOrPhoneTextbox(String p0)
{
loginPage.enterValueInUser("abcd" + p0 + "#gmail.com");
}
[When(#"I Enter (.*) in the password")]
public void WhenIEnterInThePassword(String p0)
{
loginPage.enterValueInPassword(p0);
}
[When(#"Click on the Login button")]
public void WhenClickOnTheLoginButton()
{
loginPage.clickOnLoginButton();
}
[Then(#"Application should display an error message")]
public void ThenApplicationShouldDisplayAnErrorMessage()
{
Console.WriteLine("Verification");
// loginPage.Shutdown();
}
}
}
It may sound like off topic, but still...
I'm not sure it makes sense to use ExtentReports for you automation frameworkwritten in C#.
Starting from v.4 ExtentReports they don't support it anymore.
The reply from them was that they were going to support only Java.
This is a feature of NUnit 3. You should install the Visual Studio Test Adapter ( https://github.com/nunit/docs/wiki/Visual-Studio-Test-Adapter ) via NuGet package named "NUnit3TestAdapter" to get the OneTimeSetup to work.
Then you can check your implementation of the report :-)
Maybe your report is created in the temporary folder (after some time I found it, using windows search). I have the same when running my tests, using Visual Studio. Try to run your test, using Nunit console application. Download it separately, then run tests using console command
nunit "path to compiled .dll with tests"
In this case, I think you should found reports near .dll file. This happens in my case (using Allure reports).

FindsBy from SeleniumExtras can't find IWebElement

I've updated packages from my project on Mac and find out that PageObjects has been moved to SeleniumExtras. I struggle to use it but the error "System.NullReferenceException : Object reference not set to an instance of an object." is shown.
Nevertheless, the same element can be found through FindElement. Currently, I run out of ideas and would appreciate the help.
Thanks!
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NUnit.Framework;
using NUnit.Compatibility;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using SeleniumExtras.PageObjects;
namespace SomeTest
{
[TestFixture]
public class UnitTest1
{
[FindsBy(How = How.XPath, Using = "//*[#id='lst-ib']")]
public IWebElement _searchField;
public IWebDriver chrome;
[SetUp]
public void TestMethod1()
{
chrome = new ChromeDriver(#"/Volumes/Macintosh HD/QA/SomeTest/SomeTest/bin/Debug/netcoreapp2.1");
}
[Test]
public void SomeTest()
{
chrome.Navigate().GoToUrl("https://www.google.com/");
_searchField.SendKeys("Some Text");
}
[TearDown]
public void CloseBrowser()
{
chrome.Close();
}
}
}
Got solution:
Add all DotNetSeleniumExtras through NuGet Packages: PageObjects and PageObjects.Core;
Add namespaces:
using FindsByAttribute = SeleniumExtras.PageObjects.FindsByAttribute;
using How = SeleniumExtras.PageObjects.How;

C# UI Test being ignored and not running?

So I wrote a test and am trying to run it but when I right click it and hit, "Run Selected Test" the green loading bar moves up for less than a second and just stops. Fairly new to this so excuse my ignorance.
Test being ignored & not running.
This is the stack trace I get from the test output when I try to run it.
This is my session class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;
public class CCSession
{
// Note: append /wd/hub to the URL if you're directing the test at Appium
protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
protected static WindowsDriver<WindowsElement> session;
private const string ExcelAppId = #"C:\Program Files\Microsoft Office\root\Office16\EXCEL.exe"; // test
public static void Setup(TestContext context)
{
// Launch Excel application if it is not yet launched
if (session == null)
{
// Create a new session to launch Excel application
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", ExcelAppId);
appCapabilities.SetCapability("deviceName", "WindowsPC");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
Assert.IsNotNull(session);
session.FindElementByName("Blank workbook").Click();
// Verify that Excel is started with untitled new file
Assert.AreEqual("Book1 - Excel", session.Title);
// Set implicit timeout to 1.5 seconds to make element search to retry every 500 ms for at most three times
session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1.5);
}
}
public static void TearDown()
{
// Close the application and delete the session
if (session != null)
{
session.Close();
try
{
// Dismiss Save dialog if it is blocking the exit
session.FindElementByName("Don't Save").Click();
}
catch { }
session.Quit();
session = null;
}
}
}
Test class:
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Api.Dto;
using CEL.CostCalculator.Api.CalculationResults;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Remote;
using Tests.Fixtures.DataPorts;
[TestClass]
public class CCExcelAddInTests : CCSession
{
[TestMethod]
public void EditorEnterText()
{
Assert.AreEqual("Book1 - Excel", session.Title);
}
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
Setup(context);
}
[ClassCleanup]
public static void ClassCleanup()
{
TearDown();
}
}
Any help's appreciated. :)
My test projects .csproj file was corrupted. Corrected and tests are visibly running again.

invalid opcode error on invoking firefox driiver in selenium c#

I am running my selenium script on amazon work space, scripting language using is c#
when i run my script in visual studio i got a error popup with message "installer corrupted:invalid opcode" . my script run properly but each time Firefox driver instance triggered this popup also appear
Below is my code used
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
namespace Automation
{
[TestFixture]
public class Loginpage
{
private FirefoxDriver driver;
private string baseURL;
public Loginpage() { }
[SetUp]
public void LoadDriver()
{
Console.WriteLine("SetUp");
driver = new FirefoxDriver();
baseURL = "https://google.com";
}
[Test]
public void Login()
{
driver.Navigate().GoToUrl(baseURL);
}
[TearDown]
public void UnloadDriver()
{
Console.WriteLine("TearDown");
driver.Quit();
}
}
}
Can anyone please help me on this.
Thanks in Advance

BDD Specflow Object reference not set to an instance of an object in ObjectContainer.RegisterInstanceAs

I have rearranged my class files and Webdriver variable so I can use Context Injection to share the Webdriver variable between steps. Before I was using SetupFixture, Setup and TearDown which is not correct for BDD. Trying Context Injection now with BeforeAllTests, BeforeTestRun etc.
I am getting the error:
System.NullReferenceException: Object reference not set to an instance of an object
The line highlighted where the error is here:
[BeforeScenario]
public void RunBeforeScenario()
{
objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
}
My setup.cs implementation is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium.Firefox;
using SearchTest.Setup;
using BoDi;
using SearchTest.WebDriver;
namespace SearchTest.Setup
{
[Binding]
public class BeforeAllTests
{
private readonly IObjectContainer objectContainer;
private static SeleniumContext seleniumContext;
public BeforeAllTests(IObjectContainer container)
{
this.objectContainer = objectContainer;
}
[BeforeTestRun]
public static void RunBeforeAllTests()
{
seleniumContext = new SeleniumContext();
}
[BeforeScenario]
public void RunBeforeScenario()
{
objectContainer.RegisterInstanceAs<SeleniumContext>(seleniumContext);
}
}
}
My HomePage class HomePage.cs implementation is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium.Firefox;
using NUnit.Framework;
using SearchTest.Setup;
using SearchTest.WebDriver;
using TechTalk.SpecFlow;
using BoDi;
namespace SearchTest.PageObjects
{
[Binding]
public class HomePage : PageObjectBase
{
private SeleniumContext seleniumContext;
//private IWebDriver driver{ get; set; }
[FindsBy(How = How.XPath, Using = ".//TITLE")]
public IWebElement Title{ get; set; }
// search text field on the homepage
//[FindsBy(How= How.Id, Using="twotabsearchtextbox")]
//private IWebElement Searchfield_ID { get; set; }
[FindsBy(How = How.XPath, Using = ".//*[#id='twotabsearchtextbox']")]
private IWebElement Searchfield_XPATH { get; set; }
[FindsBy(How = How.Id, Using = "nav-search-submit-text")]
private IWebElement SearchButton { get; set; }
[FindsBy(How = How.XPath, Using = ".//*[#id='nav-search']/form/div[2]/div/input")]
private IWebElement searchButton_Xpath {get; set;}
// public HomePage(IWebDriver driver)
public HomePage(SeleniumContext seleniumContext)
/*This is to reference the PageObjectBase Class. Passing in the Title of the
* page that is expected for the HomePage to ensure the correct Page is loaded
* before starting any tests.
*/
//: base("Amazon.co.uk: Low Prices in Electronics, Books, Sports Equipment & more")
: base(seleniumContext)
{
//driver = new FirefoxDriver();
//Console.Out.WriteLine("from Homepage Constructor Driver.title in SearchResultsPage class = " + driver.Title);
//driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5)); // Set implicit wait timeouts to 5 secs
//PageFactory.InitElements(driver, this);
this.seleniumContext = seleniumContext;
PageFactory.InitElements(seleniumContext.driver, this);
}
public void goToURL() {
//driver.Navigate().GoToUrl("http://www.amazon.co.uk");
}
public void EnterSearchText(String text)
{
Searchfield_XPATH.SendKeys(text);
}
public SearchResultsPage click_search_button() {
searchButton_Xpath.Click();
return new SearchResultsPage(seleniumContext);
}
}
}
Steps class SearchSteps.cs implementation is:
using System;
using TechTalk.SpecFlow;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using NUnit.Framework;
using SearchTest.PageObjects;
using SearchTest.WebDriver;
namespace SearchTest
{
[Binding]
public class SearchSteps
{
private SeleniumContext seleniumContext;
private IWebDriver driver { get; set; }
PageObjects.HomePage home_page { get; set; }
private SearchResultsPage search_results_page;
[Given(#"I navigate to the page ""(.*)""")]
public void GivenINavigateToThePage(string p0)
home_page = new PageObjects.HomePage(seleniumContext);
//home_page.goToURL();
}
[Given(#"I see the page is loaded")]
public void GivenISeeThePageIsLoaded()
{
//Assert.AreEqual("http://localhost:8080: PS4 products", driver.Title);
}
[When(#"I enter Search Keyword in the Search Text box")]
public void WhenIEnterSearchKeywordInTheSearchTextBox(Table table)
{
//string search_text = table.Rows[0]["Keyword"].ToString();
//driver.FindElement(By.Id("twotabsearchtextbox")).SendKeys(search_text);
//SearchResultsPage SearchResultsPage = home_page.EnterSearchText("F1");
home_page.EnterSearchText("F1");
}
[When(#"I click on Search Button")]
public void WhenIClickOnSearchButton()
{
//driver.FindElement(By.Name("BtnG")).Click();
search_results_page = home_page.click_search_button();
}
[Then(#"Search items shows the items related to PS4")]
public void ThenSearchItemsShowsTheItemsRelatedToPS4()
{
//Assert.AreEqual("PS4", driver.FindElement(By.XPath(".//*[#id='desktop-auto-sparkle-multi']/div/a")).Text);
//Assert.AreEqual("PS4", driver.FindElement(By.XPath("//h2[contains(text(), "PS4")]")));
search_results_page.get_search_result_title();
}
}
}
How do I resolve this please?
I think it is complaining that objectContainer.RegisterInstanceAs does not have any value, it is Null. It has not been instantiated?
Thanks, Riaz
your problem is that you have a typo in your constructor. This:
public BeforeAllTests(IObjectContainer container)
{
this.objectContainer = objectContainer;
}
should be
public BeforeAllTests(IObjectContainer container)
{
this.objectContainer = container;
}
you are not using the container instance given in the constructor, you are simply setting the objectContainer to itself.

Categories