Thursday, 7 June 2018

Selenium : How to upload file in selenium WebDriver using C#

Selenium: How to upload the file in selenium WebDriver using C#

In many of the test scenarios, we need to upload file to test that file upload features are working or not. In case of image file we need to ensure that uploaded images are properly displayed. At the time of writing an automated script on file upload we have to interact with the web element as well as windows file upload dialog. Our Selenium WebDriver API can only works on clicking the button to display the File Upload dialog but cannot interact with the file dialog. In this situation, we need to use the power of C#.
.Net has a library to handle file upload dialog. It has a SendKeys class that has a method SendWait(string keys). It sends the given key on the active application and waits for the message to be processed. It does not return any value.
image
Common syntax to use this command,
SendKeys.SendWait(string keys);
Here keys is the string of keystrokes.
For example in C#,
image
The first line of SendKeys.SendWait() takes a string as an argument that it writes the file name text box of file upload window.
The second line of SendKeys.SendWait() takes a string like “{Enter}” that it executes the enter key from keyboard.
Note that we need to add System.Windows.Forms namespace to get this method.
image
Lets do a short project on how we can implement in our test scenario. For example we have the following page where we have to upload an image.
Page link : http://nervgh.github.io/pages/angular-file-upload/examples/image-preview/
image
Step 1 : Open Visual Studio and create a new project with Console Application type.
image
Step 2 : Add a reference for Webdriver from Nuget package manager. How to add a reference from Nuget package can be found in my another post.
image
Step 3 : Write the following code for opening page using Firefox Browser under static void Main(string[] args) method.
image
Note that we need to add following namespaces for webdriver.
image
Step 4 : Write the code for clicking on Browse button of the page to open file upload dialog.
image
Step 5 : Write the code to handle file upload dialog to browse image and click open button.
image
image
Note : Sometimes we need to add Thread.Sleep(30) method between these two SendKeys.SendWait() method to stop to press enter key until File name typing is complete. We see system sometimes try to type quickly on file name box and do missing some part from beginning and at the time if enter key pressed System throws a invalid file path error message. To prevent this message we use this statement. We have to add System.Threading namespace to implement this statement.
Note that we need to add the following namespace SendKeys.SendWait().
image
We will not get this namespace if we do not add “System.Windows.Forms” reference from Reference manager window. We get this reference by right clicking on Reference and click on Add Reference option.
image
image
Reference section will be,
image
Step 6 : Click on Upload button of the page.
image
image
Step 7 :  Now close the driver. Main method will be,
image
Step 8 : Run the application by clicking on Start button. It opens the browser and upload the image file using SendKeys.SendWait() methods.
That’s all for now. In our future post we will show on how we can upload file using Java.
Till then ….Happy scripting with Selenium  Webdriver using the power of C#.

Wednesday, 6 June 2018

ExtentReports used for Nunit with Specflow

I just finished a simple test project by using Nunit and Specflow, and if you want to generate a beautiful report with ExtentReports, the file you need to change is only the Hooks.
The following is my steps how to implement.

namespace SpecPara
{
    [Binding]
    public class Hooks
    {
        //Global Variable for Extend report
        private static ExtentTest featureName;
        private static ExtentTest scenario;
        private static ExtentReports extentReports;

        //the context injection and  IObjectContainer
        public readonly IObjectContainer _ObjectContainer;
        private IWebDriver _driver;

        public Hooks(IObjectContainer iObjectContainer)
        {
            _ObjectContainer = iObjectContainer;
        }

        [BeforeTestRun]
       
        public static void InitializeReport()
        {
            Console.WriteLine("BeforeTestRun");
            //Create the html report,//Initialize Extent report before test starts
            var htmlReport =
                new ExtentHtmlReporter(
                    @"C:\Users\hzha321\RiderProjects\SelelniumParallenTest\SpecPara\Report\exReport.html");
            htmlReport.Configuration().Theme = AventStack.ExtentReports.Reporter.Configuration.Theme.Dark;
//            Attach report to reporter
            var extent = new ExtentReports();
            extentReports.AttachReporter(htmlReport);
        }

        [AfterTestRun]
        public static void TearDownReport()
        {
            Console.WriteLine("AfterTestRun");
            //Flush report once test completes
            extentReports.Flush();
        }

        [BeforeFeature]
        public static void BeforeFeature()
        {
            Console.WriteLine("BeforeFeature");
            //Create dynamic feature name
            featureName =
                extentReports.CreateTest<AventStack.ExtentReports.Gherkin.Model.Feature>(FeatureContext.Current
                    .FeatureInfo
                    .Title);
        }

        [AfterStep]
        public void InserReportSteps()
        {
            Console.WriteLine("AfterStep");

            var stepType = ScenarioStepContext.Current.StepInfo.StepDefinitionType.ToString();
            PropertyInfo pInfo =
                typeof(ScenarioContext).GetProperty("TestStatus", BindingFlags.Instance | BindingFlags.NonPublic);
            MethodInfo getter = pInfo.GetGetMethod(nonPublic: true);
            object TestResult = getter.Invoke(ScenarioContext.Current, null);

//to get the pass fail status from testcase.
            if (ScenarioContext.Current.TestError == null)
            {
                switch (stepType)
                {
                    case "Given":
                        scenario.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.ToString());
                        break;
                    case "When":
                        scenario.CreateNode<When>(ScenarioStepContext.Current.StepInfo.ToString());
                        break;
                    case "Then":
                        scenario.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.ToString());
                        break;
                    default:
                        break;
                }
            }
            else if (ScenarioContext.Current.TestError != null)
            {
                switch (stepType)
                {
                    case "Given":
                        scenario.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.ToString())
                            .Fail(ScenarioContext.Current.TestError.InnerException);
                        break;
                    case "When":
                        scenario.CreateNode<When>(ScenarioStepContext.Current.StepInfo.ToString())
                            .Fail(ScenarioContext.Current.TestError.InnerException);
                        break;
                    case "Then":
                        scenario.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.ToString())
                            .Fail(ScenarioContext.Current.TestError.Message);
                        break;
                    default:
                        break;
                }
            }

            //Pending Status
            if (TestResult.ToString() == "StepDefinitionPending")
            {
                if (stepType == "Given")
                    scenario.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.Text)
                        .Skip("Step Definition Pending");
                else if (stepType == "When")
                    scenario.CreateNode<When>(ScenarioStepContext.Current.StepInfo.Text)
                        .Skip("Step Definition Pending");
                else if (stepType == "Then")
                    scenario.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.Text)
                        .Skip("Step Definition Pending");
            }
        }

        [BeforeScenario]
        public void Initialize()
        {
            Console.WriteLine("BeforeScenario");
            //Create dynamic scenario name
            scenario = featureName.CreateNode<Scenario>(ScenarioContext.Current.ScenarioInfo.ToString());
            _driver = new ChromeDriver();
            //the most important step
            //register the instance object
            _ObjectContainer.RegisterInstanceAs<IWebDriver>(_driver);
        }

        [AfterScenario]
        public void ClearUp()
        {
            Console.WriteLine("AfterScenario");
//            Driver.Quit();
        }
    }
}

In total, the main thing can be divided into 3 main parts:

Tuesday, 29 May 2018

Postman: chaining requests

Most people already know how to send a lone request using Postman. Send it off, inspect the response you get from the server. Make some adjustments, and then try it again.
That’s all well and good. However, when you save one or more requests to a collection, you can start using some of the more advanced features in Postman. For example, with Postman, you can write scripts that run before and/or after you send your request and receive a response from the server.
There’s a lot more you can do with these scripts.
  • Do setup and teardown for testing. For example, you can do calculations to use in the main request or send asynchronous requests. Tests scripts are the cornerstone of testing in Postman – to validate your endpoint is working as expected.
  • Direct the next request to be called based on the results of the server response. Using basic JavaScript, you can then use postman.setNextRequest("Request name") to guide the sequence of the remaining API calls.
  • Extract data from the response. This can be useful to capture session or cookie data or parse information available within the response body to chain requests. In this tutorial, we’ll dig deeper into this scenario.

Set up a Bitcoin tracker

Have you heard of Bitcoins?!? It's one of many cryptocurrencies based on blockchain technology, something about maths, and… well, there's probably more I should know about that. What I did know, however, is someone who accidentally purchased 200 Ethereum (another cryptocurrency), instead of $200 worth of Ethereum. With this fortunate mistake, he made enough money to pay for his son's college tuition over the course of 2 weeks  
How can you make money when the price of Bitcoins are so volatile? Turns out, you can make money because the price of Bitcoins are so volatile.
I had serious fear of missing out (FoMO), and wanted to gamble on invest in Bitcoin too! The next time the price of Bitcoin fell to a reasonably low rate, I planned to fill my coffers with Bitcoins like Scrooge McDuck.
Let's walk through how to extract data from a response and chain together requests. 
  1. Create and select an environment.
    • For this example, we’ll create and select a new environment. We’ll use this environment to store and access our environment variables. Update the values using your own Twilio API credentials. We'll be using the Twilio API to send ourselves an SMS when the price of Bitcoin falls to certain price. Sign up for a Twilio test account if you don't already have one.
  2. Send a GET request, extract data from the response, and store as an environment variable.
    • Send a GET request  to https://api.coindesk.com/v1/bpi/currentprice.json using Postman. This request returns a JSON body. Remember to save this request to a collection. We'll see why this is important in just a bit.
    • Under the Tests tab, add the following JavaScript. The important thing to know here is that we can access the JSON response body using pm.response.json(), and then parse the response object to extract the current Bitcoin rate. Then we can store this value as an environment variable using pm.environment.set("rate", usdRate) where "rate" is the name of our environment variable and usdRate is the value that we'll store as this variable. 
    • After we hit Send, click on the Quick Look icon to see that we’ve extracted the data from the response body, and saved it as an environment variable. Now, we can use this variable in our next request.
    • In the same manner, can you figure out how to extract the "time" from the response, and then save it as an environment variable?
  3. Send a POST request using a stored environment variable. 
    • For this second request, we will use the Twilio API to send an SMS. Send a POST to https://api.twilio.com/2010-04-01/Accounts/{{twilioAccountSID}}/Messages.jsonwhere {{twilioAccountSID}} is your own Twilio Account SID. Remember to also save this second request to our collection.
    • String substitution: we can use the double curly braces syntax anywhere we would normally input text, like {{variable-name}}, to use a variable. Postman will access the variable's value and swap in the value as a string. Use the double curly braces in the URL, parameters, or any of the other data editors.
    • More String Substitution: this request requires the authentication credentials we saved to our environment in the first step. We can use the same double curly braces syntax in Postman's auth helper to handle Basic Auth for the Twilio API. Authentication (and scripts) are available for entire collections and folders too.
    • Special note about accessing variables in scripts: there's a different way to access variables in the script sections since we're writing JavaScript, instead of text. Under the pre-request or tests script tabs, use pm.variable.get("variable-name").
  4. Run the collection
    • Instead of sending your requests one at a time, you can run every request in the collection in one go. Run the collection locally with collection runner in the Postman app or with the Newman command line tool. Alternatively, you can run the collection and environment on the Postman cloud as a monitor.
Postman Tip: you can send these requests in the default, ordered sequence, or you can write a script to execute these calls in a specified sequence using postman.setNextRequest("Request name") or to terminate the remaining collection run using postman.setNextRequest(null). In this manner, you can build a sequence of API calls that mirror your use case.

Try it yourself

Click the orange Run in Postman button to import the Bitcoin Tracker collection and environment into your Postman app. 
Run in Postman
  1. Enter your Twilio credentials: You will need a Twilio Account SID to update the twilioAccountSID value within the Postman environment. You will need a Twilio Auth Token to update the twilioAuthToken value within the Postman environment.
  2. Enter a target rate: In this example, set a target rate by updating the targetRate value within the Postman environment. If the current Bitcoin rate drops below this target, like in a flash crash, the POST request to the Twilio API will be called.
  3. Run it: Run the collection and environment locally using the Postman collection runner.

Need help getting started? Check out the documentation for the Bitcoin Tracker, and follow along with step-by-step instructions, examples of responses, and helpful screenshots.


Monday, 14 May 2018

30 Days of E-Commerce Testing -Day 15-Name five different online payment methods.


Name five different online payment methods.
When you run a global business, you may want to integrate credit cards to collect payments, however, you will find most countries have their own popular local payment methods.
  • American like paypal and credit card.
  • Chinese prefer e-wallet Alipay

  • In Germany, the major local payments are online banking sofortBanking, Giropay, and Paysafecard.
  • Dutch like iDeal
  • Polish use Dotpay
  • Arab prefer E-wallet like CashU.
  • Russia, people like E-wallet like Qiwi, Yandex.Money, Webmoney and cash.
  • Online banking transfer is more popular in South East Asia.
  • People in Brazil prefer Boleto

Sunday, 13 May 2018

30 Days of E-Commerce Testing -Day 13-Share three testing ideas for an ecommerce website.

Share three testing ideas for an eCommerce website.

Function test:


1 Continue shopping
At the ‘my cart’ page, users should be given the option to add more items to the cart in case if they want to buy more items before checkout. To test the site with this function to make sure it works.

2 Search results page
Search for the items is a commonly used function. At search page, the sort order is important. In my opinion, a user generates search order like ‘top-rated’, ‘best sellers’, ‘price’(low to high or high to low) etc. should be tested.


Performance test:


3 Generally speaking, there might have a large amount users login or checkout simultaneously, testing concurrent of login API and check out API is essential to make sure the website could work stably under the a certain concurrent. 

Saturday, 12 May 2018

30 Days of E-Commerce Testing -Day 12-Create a mindmap of what ecommerce testing means to you and share it!





30 Days of E-Commerce Testing -Day 11-Test a “my cart” page from different user persona’s perspectives, share your personas!

Test a “my cart” page from different user persona’s perspectives, share your personas!

Here are my personas for the cart, and I separate people into three age group, that is three personas young people, middle age, and elderly persons.

Persona 1: For young people, they catch up new things and technologies and like all the things that fancy and fashionable. So the cart should be cool and display all the thing that in order. As a young people,  the cart page should be loaded fast and UI should be attractive.

Persona 2: As middle age person, normally they have the family to feed and they are price sensitive. So at the cart page , uses promotions and coupons where possible.

Persona 3: For the elderly people, they are not involved a lot with the internet, and most of the time asks for help to others.  So they would be grateful to have a user-friendly interface and an intuitive page. A help window at cart page would be helpful for getting them out of troubles.

What to do to make sure HTML Table is loaded completely if implicit and explicit wait are not working.

These days I was working on a project, to implement the delete function of a listing. Such as below: Actually,  every time deleted the it...