Disposable Emails with Cucumber

Automating Registration Functionality Using Disposable Emails with Cucumber


Cucumber is an extremely popular behavior-driven test framework used by developers around the world. It started as a Ruby project but now supports many languages and use cases. In this example we shall show users the usage of Cucumber with JUnit.

In this post it is assumed that you are familiar with cucumber-JUnit. If you haven't any idea about cucumber-JUnit and its configuration then you can go through the cucumber docs

Mail7 is a free Email API that lets you generate random email addresses on demand for use in tests. You can use them to send and receive real emails in a range of languages (including Ruby, Java, Javascript, and more).

This post will demonstrate how to use Mail7 with Cucumber to test any email related process with real emails.

The Gherkin Syntax

Cucumber tests are built around human-readable scenarios written in Gherkin syntax. These tests look a bit like this:

Scenario: A user visits my website
  Given the user is new
  When the user clicks login
  Then the sign-up screen is shown

Testing Email with Cucumber

To test email using real emails all we need to do is wire Mail7 into our Cucumber tests. Let's write an example in cucumber-JVM to demonstrate.

Why Need of Mail7

Assuming that if you sign up for a new account using an email address, you will be required to verify that you control the address you want to register before gaining access to the new service. This usually involves clicking a link embedded in an email sent to the address in question.

What Makes This Hard?

In our scenario, the email address is our unique identifier for a user. That means we can’t register with the same address more than once. One easy but not scalable solution for testing is to use many addresses you have access to.

How can you test that your code triggers the message to be sent and that the message gets delivered to a real mailbox?

Use A Disposable Email Service

A more robust solution to this problem is to use a disposable email. You can send an email to any address hosted at these services and then manually check that inbox to see if your mail arrived. You can append the date or timestamp (depending on your testing frequency), to ensure the uniqueness of your address. In case you need it, Mail7 also allows you to send emails.

Automate

There are also ways you can get access to an API for one of the many disposable email services. Using an API will allow you to programmatically check for the delivery of your email to a mailbox within their service. For a small monthly fee you can upgrade your service to paid plans.

Setup

To use JUnit to execute cucumber scenarios add the cucumber-JUnit dependency to your pom.

<dependencies>
  [...]
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
  [...]
</dependencies>

Cucumber is based on JUnit 4. If you’re using JUnit 5, remember to include JUnit-vintage-engine dependency, as well.

Now Create an empty class that uses the Cucumber JUnit runner.

package com.example;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions()
public class RunCucumberTest {
}

Writing tests

Cucumber tests live in a features folder. Let's create that and add a new test feature and some step definitions.

features
├── can_i_send_and_receive_email.feature
└── stepDefinitions
    └── stepdefs.java

Inside the .feature file let's write a Gherkin scenario that tests the sending and receiving of an email in a Cucumber test.

Feature: User Signup and Emai Verification?
  Send and receive real emails in Cucumber using Mail7

  Scenario: Successful Login with Valid Credentials
    Given User Launch Chrome Browser
    When User opens URL "http://yourdomain.com/signup-page-url"
    And User enters Email as "<emailaddress>" and Password as "<password>"
    And Click on Login
    Then Page Title should be "<ExpectedResult>"
    And close browser
    
    Examples:
    | firstname   | emailaddress          | password       | ExpectedResult |
    | First       | [email protected]    | @StrongPass#98 | Successful     |
    | Second      | [email protected]   | MissingNumber  | Fail           |

If we run bundle exec cucumber Cucumber will tell us (rightly) that we are missing step definitions for each When Then clause. We will define those next.

Defining steps

The magic of Cucumber tests happens in your steps files. Theses files map Gherkin scenarios to real logic in your chosen programming language. Here we are using java as it is popular but mail7 supports all other Cucumber supported languages.

Inside stepdefs.java let's add the following:

/*
//import the package here
package step definitions;

//import the class dependencies here
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.*;
import org.junit.Assert;
import pageObjects.SignUpPage; // Signup page object model
*/

public class Steps {
    
    public WebDriver driver;
    public SignUpPage signuppage;
    
    @Given("^User Launch Chrome Browser$")
    public void user_Launch_Chrome_Browser() throws Throwable {
       System.setProperty("webdriver.chrome.driver", 
               System.getProperty("user.dir")+"//path-to-driver/chromedriver.exe");
       driver = new ChromeDriver();
       
       signuppage = new SignUpPage(driver);
    }
    @When("^User opens URL \"([^\"]*)\"$")
    public void user_opens_URL(String url) throws Throwable {
        driver.get(url);
        Thread.sleep(18000);
    }
    @When("^User enters Email as \"([^\"]*)\" and Password as \"([^\"]*)\"$")
    public void user_enters_Email_as_and_Password_as(String email, String password) 
            throws Throwable {
        signuppage.setEmail(email);
        signuppage.setPassword(password);
    }
    @When("^Click on Login$")
    public void click_on_Login() throws Throwable {
        signuppage.clickLogin();
        Thread.sleep(18000);
    }
    @Then("^Page Title should be \"([^\"]*)\"$")
    public void page_Title_should_be(String title) throws Throwable {
       if(driver.getPageSource()
               .contains(ExpectedResult)) {
           driver.close();
           Assert.assertTrue(true);
       } else {
           Assert.assertEquals(title, driver.getTitle());
       }
    }
    @Then("^close browser$")
    public void close_browser() throws Throwable {
        driver.quit();
    }
}

Configuring Mail7

You need an API Key and Secret to use Mail7 but it is free for personal use. Get an API Keys here then create test cases and use the below logic to receive the email body of sent mail

⚠️ Note: Mail7 requires an API key and API secret. You can get one free in the dashboard.

Writing email logic

Inside ExampleUsageTest.java let's add the following:

public class ExampleUsageTest {
    private static final String YOUR_API_KEY = "your_mail7_api_key_here";
    private static final String YOUR_API_SECRET = "your_mail7_api_secret_here";

    String getEmailBody(String UserName) throws IOException {
        URL url = new URL("https://api.mail7.io/inbox?apikey=" + YOUR_API_KEY + "&apisecret=" + YOUR_API_SECRET + "&to=" + UserName);
        HttpURLConnection con;
        con = (HttpURLConnection) url.openConnection();

        // handle error response code it occurs
        int responseCode = con.getResponseCode();
        InputStream inputStream;
        if (200 <= responseCode && responseCode <= 299) {
            inputStream = con.getInputStream();
        } else {
            inputStream = con.getErrorStream();
        }

        BufferedReader in =new BufferedReader(
        new InputStreamReader(
        inputStream));

        StringBuilder response = new StringBuilder();
        String currentLine;

        while ((currentLine = in.readLine()) != null)
        response.append(currentLine);

        in .close();

        return response.toString();
    }
}

Unirest is a lightweight HTTP client library that also can be used in the above function to retrieve the GET API response

Use of getEmailBody function

public class checkemail 
{ 
    public static void main(String args[]) 
    { 
        ExampleUsageTest test1 = new ExampleUsageTest();
        
        String body = null;
        try {
            body = test1.getEmailBody("testnew");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
        System.out.println(body);
    } 
} 

Output format returned by Mail7 API

{
    "status": "success",
    "data": [
        {
            "_id": "5eb4f2cb94f95000173ea81b",
            "to_username": "<recipient username>",
            "to_domain": "mail7.io", // any domain which is used while creating email address
            "mail_source": {
                "attachments": [],
                "headers": {
                },
                "headerLines": [
                 {}
                ],
                "html": "<email body with html format>",
                "text": "<email body in text format>",
                "textAsHtml": "",
                "subject": "<subject of email>",
                "date": "<datetime>",
                "to": {}, //object
            "is_deleted": false,
            "is_read": true,
            "sender_time": "2020-05-08T05:48:59.496Z"
        }
    ]
}

Mail7 supports many other features like custom domains, attachments, email pattern matching, and more. See the about page for more information.

Next steps

Imagine the possibilities. Unlimited real email addresses at your disposal in the Cucumber test. Mail7 is free for personal use and available now