FenWangNZ / blog

I love learning. This is my wiki.
0 stars 0 forks source link

Starting automation test on invoice module-Create an invoice #10

Open FenWangNZ opened 3 years ago

FenWangNZ commented 3 years ago

Introduction

Now I need to work on a new module(There are only two modules available in this accounting software, however for practice, that's enough!) Today I move on to develop automation test framework to improve my previous ugly tests and also to show how to develop it step by step.

  1. Create a new class in the same project.
[TestClass]
[TestCategory("InvoiceModule")]
public class InvoiceTests
{
    [TestMethod]
    [Description("Create a non-zero amount invoice, including testing the 2 hidden buttons")]
    public void Test_CreateNewInvoice()
        {
    }
}
  1. copy this bit because I need to login before going to Invoice page.
//Define parameters in class level
IWebDriver driver;
LoginPage loginPage;
InvoicePage invoicePage;
TestUser userInfo;

[TestInitialize]
public void SetupBeforEverySingleMethod()
{
driver = ChromeDriver();
loginPage = new LoginPage(driver);
loginPage.Open();
driver.Manage().Window.Maximize();
userInfo = new TestUser();
userInfo.EmailAddress = "guest@guest.com";
userInfo.PassWord = "q1111111";
loginPage.InputUserInfoAndLogin(userInfo);//login to system
invoicePage = new InvoicePage(driver);//Open Invoice page.
invoicePage.Open();
}

[TestCleanup]
public void CleanupAfterEverySingleMethod()
{
driver.Close();
driver.Quit();
}
  1. Then we need to define InvoicePage.cs To open Invoice page.
using System;
using OpenQA.Selenium;

namespace CNZBATests
{
    internal class InvoicePage
    {
        public InvoicePage(IWebDriver driver)
        {
            Driver = driver;
        }

        public IWebDriver Driver { get; }

        internal void Open()
        {
            Driver.Navigate().GoToUrl("https://cbaaccountingwebapptest.azurewebsites.net/invoices/new");
        }
    }
}
  1. Add assertion in open(): (1) To see the page to be opened before proceeding to the next test step;
WebDriverWait *wait = new WebDriverWait(driver, TimeSpan.FromSeconds(6));
wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//*[@type='submit']")));

When I wrote these codes, Visual Studio C# complained because ExpectedConditions is not available in new version of Selenium.

So I added a Nuget package called DoNetSeleniumExtras.WaitHelpers. Then Add these one line in the header.

using OpenQA.Selenium.Support.UI;
using ExpectedConditions = SeleniumExtras.WaitHelpers.ExpectedConditions;

Build t until it opens the invoice page.

  1. As you can see, I reused some lines of codes in these LoginTest.cs and Invoice.cs classes, so it is time to refactor it. (1). Add BasePage.cs

This is because driver is always defiend in LoginPage.cs, InvoicePage.cs and InvoiceListPage.cs , and also Driver property is set in these palces and Classes that pass Driver parameters are defined in a same way.

(2). Driver in BasePage.cs must be protected so that its child can access it. We also need a constructor that takes in driver, set the driver to the Driver that is passed in. BasePage.cs:

using OpenQA.Selenium;
namespace CNZBATests
{
    public class BasePage
    {
        protected IWebDriver Driver { get; set; }
        public BasePage(IWebDriver driver)
        {
            Driver = driver;
        }
    }
}

It will hold a reference to our driver that is utilised by all the pages.

(3). How to use Base Page

in the child files such as LoginPage, InvoicePage, InvoiceListPage, we should force a base class to take the instance of the driver that has passed then.

so the driver definition part in LoginPage.cs was :

namespace CNZBATests
{
    internal class LoginPage
    {
        public LoginPage(IWebDriver driver)
        {
            Driver = driver;
        }

        public IWebDriver Driver { get; }

turns into:

namespace CNZBATests
{
    internal class LoginPage : BasePage
    {
        public LoginPage(IWebDriver driver) : base(driver) { }
  1. Write the skeleton of Creating a new invoice test method.
public void Test_CreateNewInvoice()
{
invoicePage.AssertDefaultValuesOnInvoiceCreationPage();//To verify the default values on Invoice Creation page.
invoicePage.CreateANonZeroInvoice();//To create a non-zero invoice and also assert the status for this created invoice.
invoiceListsPage = new InvoiceListsPage(driver);
invoiceListspage.AssertInvoiceInfoOnInvoiceLists();//To assert if this created invoice can can be searched on Invoice Tracker page
}
  1. Create AssertDefaultValuesOnInvoiceCreationPage() in InvoicePage.cs.

First: take out default values such as "10", "CNZBA", ...out of AssertDefaultValuesOnInvoiceCreationPage() method to class level. and define them as constant as follows:

//constants that are used in this method are defined at class level.
private const string CNZBA = "ABNZ";
private const string TotalLength = "10";
private const string FinalSix = "6";
private const string ZeroMoney = "0.00";
private const string DefaultStatus = "New";

So that they can be used indifferent methods.

AssertDefaultValuesOnInvoiceCreationPage() method:

internal void AssertDefaultValuesOnInvoiceCreationPage()
{
//verify invoice number
string invoiceNumber = DefaultLocators[1].Text;
Assert.AreEqual(TotalLength, Convert.ToString(invoiceNumber.Length));
string firstFiveDigits = invoiceNumber.Substring(0, 4);
string finalFiveDigits = invoiceNumber.Substring(4);
Assert.AreEqual(CNZBA, firstFiveDigits);
Assert.AreEqual(FinalSix, Convert.ToString(finalFiveDigits.Length));
//verify current date.
string currentdate = DateTime.Today.ToString("d/MM/yyyy");
Assert.IsTrue(DefaultLocators[3].Text.Contains(currentdate));
Thread.Sleep(6000);
//verify defaut value for totals and GSTs
string totalAmount1 = DefaultLocators[5].Text;
string totalAmount2 = Values[1].Text;
string GST1 = DefaultLocators[7].Text;
string GST2 = Values[2].Text;
Assert.AreEqual(ZeroMoney, totalAmount1);
Assert.AreEqual(totalAmount1, totalAmount2);
Assert.AreEqual(ZeroMoney, GST1);
Assert.AreEqual(GST1, GST2);
Thread.Sleep(2000);
//verify the defalt status is New
Assert.AreEqual(DefaultStatus, DefaultLocators[9].Text);
Thread.Sleep(2000);
//I still miss a step to verify the due date value is two weeks after current date,but becuase this datepicker is really annoying that I am not able to modify the date value;
}
  1. Write CreateANonZeroInvoice() method.

  2. Write AssertInvoiceInfoOnInvoiceLists() method.

To be continued. Still need more refactoring....