JUnit - Beyond Unit Testing: A Simple Example

Sauce AI for Test Authoring: Move from intent to executing in min.|xBack to ResourcesBlogPosted March 27, 2019

JUnit - Beyond Unit Testing: A Simple Example

Learn how to use JUnit to do acceptance and UI test on Sauce Labs

quote

Unit Testing

Thousands if not trillion of developers use JUnit for their Java unit testing. And what are they using it for? Even after 20 years of JUnit ’ s existence it is still mostly being used for unit tryout. If you are prosperous you may see an consolidation test or two.

JUnit is, in fact, much more than a unit testing model. Did you know that within your regular JUnit test suite, you canstill include acceptance exam?

Let ’ s recall Mike Cohn ’ s try pyramid:

pyramid


Source: Martin Fowler,TestPyramid, based on Mike Cohn ’ s bookSucceeding with Agile

At the bottom are regular unit tests. There are a lot of these because we aim to continue as much of our code as possible.

But unit test entirely tests parts of our code in isolation - it can ’ t see how thing play together. For that, we feature those two layers above:

  • Service / integration testing- fashioning sure the components of our application are glued together properly. For exemplar, ensuring that our logging in place and that our controller can deserialize a postulation into a protected entry in our database.

  • UI / acceptance testing- making sure a lineament in the package actually works from the user ’ s perspective. For example, your user can click to add an item to their shopping cart and checkout.

The pyramid guides as to have a variety of tests of assorted amounts based on their level. To translate why let ’ s look at an illustration. Imagine you need to test a tax calculator on an eCommerce situation. This is acrucial featurebecause if it neglect, people can ’ t buy and the company loses money.

So you write lots of unit tests to make sure every possible input to the tax estimator make the rightfield output. With these tests in place, you feel confident that no matter which country, region, currency and purchase amount are entered, the tax amount will be right.

After some tweaks, all the unit tests pass. Build is green! Ready to go!

junit images green light


But then you get a call from management (for striking upshot, let ’ s say it ’ s 2am) state the shopping cart interface is broken on the site.

You start a browser and go through the purchase operation, and then at the terminal stage, when users need to watch the tax amount, theamount isn ’ t demonstrate at all. A browser issue caused another DIV to move out of spot, and the tax amount is shroud by an ugly rectangle.

junit image browser error

So even with all those unit tests, the exploiter experience is broken. This may sound over the top but incidents like this happen ofttimes. Ensuring your fine-grained business logic is important- but just on it ’ s own, it can ’ t make sure that critical software role work end to end. That ’ s why desegregation and acceptance trial are needed.

Most of us know this in the dorsum of our psyche. Only a few of us actually venture out to indite and execute these tests. But in fact, it ’ smuch easier than you consider.

Unit tests and Selenium tests - happy neighbors?

Here ’ s a JUnit test folder of asmall Jenkins pluginwe get pen particularly for this post. On 1st glance, it looks like just any other test booklet.

junit image test folder


But take a closer look:

junit image test folder2


In this JUnit folder, endure peacefully side-by-side, are tests from all three tiers of the testing pyramid. The fourth exam list is a regular unit exam, but the top three tests in the list are actuallybased on Selenium 3.

The unit trial filehas regular material like this:

1
quickstart ...
2
@Test
3
public void successResponse () {
4
SauceStatusHelper statusHelper = new SauceStatusHelper () {
5
@Override
6
public String retrieveResults (URL restEndpoint) {
7
return & quot; {\ & quot; service_operational\ & quot;: true, \ & quot; status_message\ & quot;: \ & quot; Basic service condition cheque passed.\ & quot;} & quot;;
8
}
9
};
10
SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);
11
assertEquals (& quot; Sauce status mismatch & quot;, & quot; Basic service status checks passed. & quot;, pageDecorator.getsauceStatus ());
12
}
13
...

And the acceptance tryoutfor this Jenkins plugin have Selenium codification that drives a existent browser and simulates user activity.

For example, here ’ s a bit of code that uses a real browser (e.g. Chrome) to click the linkup “ Manage Jenkins ”, then click “ Manage Plugins ”, then verify that the plugin is installed:

1
public void pluginIsListed () {
2
//Find and pawl on the & # x27; Manage Jenkins & # x27; link
3
webDriver.findElement (By.linkText (& quot; Manage Jenkins & quot;)) .click ();
4
//It takes a few s for the page to load, so instead of lam Thread.sleep (), we use the WebDriverWait conception
5
WebDriverWait wait = new WebDriverWait (webDriver, 30);
6
wait.until (driver - & gt; driver.findElement (By.cssSelector (& quot; h1 & quot;)) .isDisplayed ());
7
//assert that we are on the Manage Jenkins page
8
assertEquals (& quot; Header not found & quot;, & quot; Manage Jenkins & quot;, webDriver.findElement (By.cssSelector (& quot; h1 & quot;)) .getText ());
9
//Find and click on the & # x27; Manage Plugins & # x27; link
10
webDriver.findElement (By.linkText (& quot; Manage Plugins & quot;)) .click ();
11
wait.until (driver - & gt; driver.findElement (By.linkText (& quot; Installed & quot;)) .isDisplayed ());
12
//Find and click on the & # x27; Installed & # x27; link
13
webDriver.findElement (By.linkText (& quot; Installed & quot;)) .click ();
14
assertEquals (& quot; Plugin link not found & quot;, & quot; Sauce Health Check plugin & quot;, webDriver.findElement (By.linkText (& quot; Sauce Health Check plugin & quot;)) .getText ());
15
   }

Does that not appear powerful? Let ’ s dive in a bit deep and see how simple it is toblanket all three level of the testing pyramid in one JUnit test suite.

SUSA automates exploratory testing with persona-driven behavior, catching bugs that scripted automation misses.

Code example with all three prove tiers: Sauce Labs Health Check

We want to show you how leisurely it can be to integrating and adoption test with JUnit. To do this, we make a simple plugin we have written is name Sauce Health Check - see it onGithub. The goal is to connect to our Sauce Labs multi-browser testing service se ensure it is up and running. Here ’ s what it does in detail:

  • Adds a line to the bottom of the Jenkins interface, like this:

junit image plugin screenshot1
  • Performs a REST call to the Sauce Labs cloud service to see its status - up or down.

  • Depending on the status, the substance will be immature and will say “ Basic service status checks passed ”, like in the screenshot; otherwise red and will say “ Sauce Labs down. ”

  • The “ Check now ” link is an AJAX call. When clicked, it shows a little “ working ” icon and re-checks the status of the service. We deliberately made this an AJAX call because that ’ s something that can alone be full tested with browser/UI automation.

junit image plugin screenshot2


In suit you ’ re wondering - why would you need to see the Sauce Labs position at the derriere of your Jenkins dashboard? No ground. It ’ s exactly the simplest piece of software we could think of that could help us demonstrate all three tiers of Java testing.

The code is uncomplicated and we won ’ t run you through it - suffice it to say that there ’ s a that tells Jenkins this is a plugin, a which calls the Sauce Labs REST API to see if the service is up or down, and a which defines how the result is displayed on the Jenkins interface.

It ’ s offset! See the tryout

As promised, here are all three tiers of testing within one JUnit tryout suite, testing the Sauce Health Check Plugin.

1. Unit Tests

The unit test occupy in. Here we have 3 functions that test what messages the PageDecorator may retrovert, depending on the Sauce Cloud ’ s condition.

The REST API is stub out to create a self-contained exam of the code. If these unit tests legislate, it means that the introductory logic of the plugin is coded correctly.

Testing when Sauce is down:

1
@Test
2
public void errorResponse () {
3
SauceStatusHelper statusHelper = new SauceStatusHelper () {
4
@Override
5
public String retrieveResults (URL restEndpoint) {
6
return & quot; {\ & quot; service_operational\ & quot;: false, \ & quot; status_message\ & quot;: \ & quot; Sauce Labs down\ & quot;} & quot;;
7
}
8
};
9
SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);
10
assertEquals (& quot; Sauce status mismatch & quot;, & quot; Sauce Labs down & quot;, pageDecorator.getsauceStatus ());
11
}

We test this because the service is seldom downward, so it is hard for us to prove this via UI automation. But we see to diligently screen against our edge cases, not only our happy paths. Now, quiz when Sauce is up:

1
@Test
2
publicvoid successResponse () {
3
SauceStatusHelper statusHelper =new SauceStatusHelper () {
4
     @Override
5
public StringretrieveResults (URL restEndpoint) {
6
return & quot; {\ & quot; service_operational\ & quot;: true, \ & quot; status_message\ & quot;: \ & quot; Basic service status checks passed.\ & quot;} & quot;;
7
     }
8
   };
9
SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);
10
assertEquals (& quot; Sauce position mismatch & quot;, & quot; Basic service status checks passed. & quot;, pageDecorator.getsauceStatus ());
11
}


And when an empty string is regress by the REST call (status unknown):

1
@Test
2
public void invalidResponse () {
3
SauceStatusHelper statusHelper = new SauceStatusHelper () {
4
     @Override
5
public StringretrieveResults (URL restEndpoint) {
6
return & quot; & quot;;
7
     }
8
   };
9
SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);
10
assertEquals (& quot; Sauce status mismatch & quot;, & quot; Unknown & quot;, pageDecorator.getsauceStatus ());
11
 }
12
}

2. Integration Test

Now we desire to check that our code incorporate with Jenkins aright by ensuring that the plugin is properly installed on Jenkins. We do this using a bit of Selenium 3 (A.K.A Selenium Webdriver) codification. The integration tests are in.

First off we define the WebDriver case variable (WebDriver is the piece of Selenium that automates the browser), and define a JUnit rule that found a local Jenkins illustration with our plugin installed.

individual WebDriver webDriver; @Rulepublic JenkinsRule jenkinsRule = new JenkinsRule ();}}

Now we start an actual Chrome browser, by creating a new ChromeDriver instance and point it to the URL of the local Jenkins example.

1
@Before
2
public void setUp () throw Exception
3
{this.webDriver = Drivers.localResourceChromeDriver ();
4
URL url = jenkinsRule.getURL ();
5
webDriver.get (url.toString ());
6
   }
7
// Our test are well-factored, so we use a helper method to new up the source-controlled driver without duplicating the codification all over our test:
8
9
public class Drivers {
10
static ChromeDriver localResourceChromeDriver () {
11
URL resource = Drivers.class.getClassLoader () .getResource (& quot; chromedriver.exe & quot;);
12
System.setProperty (& quot; webdriver.chrome.driver & quot;, resource.getPath ());
13
retrovert new ChromeDriver ();
14
   }
15
}
16

That ’ s all it lead to fire up a existent browser from within the code. Now we start the actual test - on the Jenkins dashboard, find and click the Manage Jenkins link:

@Test
public void pluginIsListed () {
//Find and clink on the & # x27; Manage Jenkins & # x27; link
webDriver.findElement (By.linkText (& quot; Manage Jenkins & quot;)) .click ();

Wait a few seconds for the page to load (remember we are on a existent Chrome browser), using the

WebDriverWait

concept, but wait only until the H1 title of the page has provide:

webDriverWait wait = new WebDriverWait (webDriver, 30);
wait.until (driver - & gt; driver.findElement (By.cssSelector (& quot; h1 & quot;)) .isDisplayed ());

Check the H1 title and ensure we are on theManage Jenkins page:

assertEquals (& quot; Header not found & quot;, & quot; Manage Jenkins & quot;, webDriver.findElement (By.cssSelector (& quot; h1 & quot;)) .getText ());

Find and click on theManage Plugins link:

webDriver.findElement (By.linkText (& quot; Manage Plugins & quot;)) .click ();

Find and click on theInstalledlink, as presently as it has rendered on the page:

webDriverWait wait = new WebDriverWait (webDriver, 30);
wait.until (driver - & gt; driver.findElement (By.cssSelector (& quot; h1 & quot;)) .isDisplayed ());

Published:
Mar 27, 2019
Share this office
Copy Share Link
LinkedIn
© 2026 Sauce Labs Inc., all rights reserved. SAUCE and SAUCE LABS are register earmark owned by Sauce Labs Inc. in the United States, EU, and may be file in other jurisdictions.
robot
quote

Automate This With SUSA

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.

Try SUSA Free

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free