loading...

Experimenting with RobotFramework and Selenium

tomerfi profile image Tomer Figenblat ・6 min read

Selenium, NUnit, and Robot Framework Walkthrough

Let me start by saying, I'm not a frontend developer by no stretch of the imagination.
I don't do web pages, or UI's...
😏

But...
As clearly stated in my profile (if it still there by the time you read this) I'm a development ecosystem enthusiast...
And I felt very enthusiastic about working with Selenium and Robot Framework.

The real story is, I was waiting for an opportunity to try out Selenium,
as a backend developer, these type of opportunities come few and far between.
That is until one day, I bumped into Robot Framework,
and I've noticed the framework has a SeleniumLibrary...

πŸ”” πŸ”” πŸ”” That rang my two-for-the-price-of-one bell! 😁

So I decided to give it a whirl... And then I thought...
Well, lately I've been writing mostly Java,
maybe this is also an opportunity to brush up on my dotnet and C# skills.
πŸ‘“

So...
To make a long story short (if that's still possible),
Here's what I came up with, hope you'll enjoy it.

Walkthrough

This is an example C# WebApp tested using Selenium
browser automation with Nunit testing framework for unit tests
and Robot Framework automation framework for acceptance tests.

Base Requirements

  • .Net Core > 3 - written with .Net Core 3.1.102.
  • Python > 3 - written with Python 3.8.2 (used for the acceptance tests).

Before starting, please clone this repository and step into the solution folder.
It will be easier to follow this tutorial, as the next steps will assume you have done so:

git clone https://github.com/TomerFi/selenium-nunit-robotframework-tutorial.git
cd selenium-nunit-robotframework-tutorial

Web Application

In src/DemoWebApp, you'll find a simple C# WebApp created from the basic template provided with dotnet.
On top of the base application I've added:

  • a button tag with the id clickmeButton.
  • a h2 tag with the id displayHeader and the initial content text of Not clicked.
  • a script function called clickButton invoked by a click event from the clickmeButton and changes the displayHeader's content text to Button clicked.

I've added these elements in src/DemoWebApp/Pages/Index.cshtml.
Other than that I've changed nothing from the basic template:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <button id="clickmeButton" type="button" onclick="clickButton()">Click Me!</button>
    <h2 id="displayHeader">Not clicked</h2>
</div>

<script>
function clickButton() {
    document.getElementById("displayHeader").textContent = "Button clicked";
}
</script>

To run the project and serve the app at http://localhost:5000:

dotnet run -p src/DemoWebApp

Unit Testing

In tests/DemoWebApp.Tests, you'll find the test project for performing unit tests, I've used:

  • Nunit as the testing framework for the project.
  • Selenium as the toolset providing browser capabilities and automation.

tests/DemoWebApp.Tests/DemoWebAppTest.cs is test class, Nunit will pick it up based on its name:

I've used the OneTimeSetup attribute to spin-up the server before executing the test cases:

[OneTimeSetUp]
public void SetUpWebApp()
{
    app = DemoWebApp.Program.CreateHostBuilder(new string[] { }).Build();
    app.RunAsync();
}

And the OneTimeTearDown attribute to shutdown the server afterward.

[OneTimeTearDown]
public void TearDownWebApp()
{
    app.StopAsync();
    app.WaitForShutdown();
}

The test itself is pretty straightforward:

  • It first navigates to the server at http://localhost:5000.
  • It will then find the button element by its id and click it.
  • Finally, it will make sure the h2 element's content text is Button clicked.

The assert statement evaluates the clicked boolean value,
which will be false if expected test conditions are not met within 10 seconds.

public void TestButtonClick(Type drvType)
{
    bool clicked;
    using (var driver = (IWebDriver)Activator.CreateInstance(drvType))
    {
        var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
        driver.Navigate().GoToUrl("http://localhost:5000");
        driver.FindElement(By.Id("clickmeButton")).Click();

        clicked = wait.Until(ExpectedConditions.TextToBePresentInElement(
            driver.FindElement(By.Id("displayHeader")), "Button clicked"));
    }
    Assert.True(clicked, "button not clicked.");
}

The test-cases will invoke the TestButtonClick test 3 times, one for each TestCase.
The result will be 3 tests performed, one with the chrome driver, one with the firefox driver, and one with the ie driver.

[TestCase(typeof(ChromeDriver))]
[TestCase(typeof(FirefoxDriver))]
[TestCase(typeof(InternetExplorerDriver))]
public void TestButtonClick(Type drvType)
{
    ...
}

To check it out, just:

dotnet test

Acceptance Testing

For acceptance tests I've used:

For the next steps, step into the acceptance folder.
The acceptance tests don't have, nor should it have, any direct
connection to the solution's base code.

Prepare Environment

Robot Framework is a python tool, it requires a python binary and some requirements.
Assuming you have Python installed, and you're in the acceptance folder,
Just do:

pip install --upgrade -r requirements.txt

As this is the acceptance tests part, the tests need a web server serving the web app.
You can follow the Web Application section to run the web app locally, or run it as you see fit.
just don't forget to set the URL variable in acceptance/resources.robot to the correct address:

${URL}              http://localhost:5000

Please note, markdown doesn't support robotframework syntax highlighting natively.
There's another version of this tutorial in restructuredText which supports robotframework syntax highlighting
here.

Drivers

You can download the drivers stored in acceptance/drivers with the following links.
Just mind the versions and make sure they're in conjunction with the versions used in
tests/DemoWebApp.Tests/DemoWebApp.Tests.csproj:

<ItemGroup>
    <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="83.0.4103.3900" />
    <PackageReference Include="Selenium.WebDriver.IEDriver" Version="3.150.1" />
    <PackageReference Include="Selenium.Firefox.WebDriver" Version="0.26.0" />
</ItemGroup>

To save you the troubles, here are the links for the drivers download:

Tests

acceptance/webapp_tests.robot is the test suite.
It declares 3 Test Cases, one for each driver.
Each test-case uses Test Template with its own Browser and Executable arguments.
Make sure the driver executables are in the correct path.

*** Settings ***
...
Test Template    Press Button

*** Test Cases ***             Browser    Executable
Test With Chrome               chrome     drivers/chromedriver
Test With Internet Explorer    ie         drivers/iedriver
Test With Firefox              firefox    drivers/geckodriver

The Test Template invokes the keyword named Press Button,
For each execution, what Press Button does is pretty self-explanatory by its BDD nature:

*** Keywords ***
Press Button
    [Arguments]    ${browser}    ${executable}
    Open Browser With Url    ${browser}    ${executable}
    Click Test Button
    Validate New Text
    [Teardown]    Close Browser

The result of running this test suite will be 3 tests, one for each driver, each pressing the button and validating the side effects.

The Press Button uses 4 other keywords to perform its action.
As you can see in the Settings section, I've declared acceptance/resources.robot as a resource.
It provides us with the following custom keywords:

  • Open Browser With Url
  • Click Test Button
  • Validate New Text

The 4th keyword, Close Browser, is not a custom one, it comes from SeleniumLibrary, imported within acceptance/resources.robot:

*** Settings ***
...
Library          SeleniumLibrary

The same library is also used in by the custom keywords in acceptance/resources.robot.

To execute the acceptance tests, simply run:

robot -d rfoutput webapp_tests.robot

This will run the tests and save a pretty and useful HTML report summary and xml logs in a folder called rfoutput (gitignored).
You can see an example of the summary report here.

Links

πŸ‘‹ See you in the next tutorial πŸ‘‹

Discussion

pic
Editor guide