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
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:

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!

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.

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.

But take a closer look:

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:
1quickstart ...2@Test3public void successResponse () {4SauceStatusHelper statusHelper = new SauceStatusHelper () {5@Override6public String retrieveResults (URL restEndpoint) {7return & quot; {\ & quot; service_operational\ & quot;: true, \ & quot; status_message\ & quot;: \ & quot; Basic service condition cheque passed.\ & quot;} & quot;;8}9};10SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);11assertEquals (& 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:
1public void pluginIsListed () {2//Find and pawl on the & # x27; Manage Jenkins & # x27; link3webDriver.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 conception5WebDriverWait wait = new WebDriverWait (webDriver, 30);6wait.until (driver - & gt; driver.findElement (By.cssSelector (& quot; h1 & quot;)) .isDisplayed ());7//assert that we are on the Manage Jenkins page8assertEquals (& 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; link10webDriver.findElement (By.linkText (& quot; Manage Plugins & quot;)) .click ();11wait.until (driver - & gt; driver.findElement (By.linkText (& quot; Installed & quot;)) .isDisplayed ());12//Find and click on the & # x27; Installed & # x27; link13webDriver.findElement (By.linkText (& quot; Installed & quot;)) .click ();14assertEquals (& 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:

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.

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@Test2public void errorResponse () {3SauceStatusHelper statusHelper = new SauceStatusHelper () {4@Override5public String retrieveResults (URL restEndpoint) {6return & quot; {\ & quot; service_operational\ & quot;: false, \ & quot; status_message\ & quot;: \ & quot; Sauce Labs down\ & quot;} & quot;;7}8};9SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);10assertEquals (& 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@Test2publicvoid successResponse () {3SauceStatusHelper statusHelper =new SauceStatusHelper () {4@Override5public StringretrieveResults (URL restEndpoint) {6return & quot; {\ & quot; service_operational\ & quot;: true, \ & quot; status_message\ & quot;: \ & quot; Basic service status checks passed.\ & quot;} & quot;;7}8};9SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);10assertEquals (& 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@Test2public void invalidResponse () {3SauceStatusHelper statusHelper = new SauceStatusHelper () {4@Override5public StringretrieveResults (URL restEndpoint) {6return & quot; & quot;;7}8};9SauceStatusPageDecorator pageDecorator = new SauceStatusPageDecorator (statusHelper);10assertEquals (& 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@Before2public void setUp () throw Exception3{this.webDriver = Drivers.localResourceChromeDriver ();4URL url = jenkinsRule.getURL ();5webDriver.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:89public class Drivers {10static ChromeDriver localResourceChromeDriver () {11URL resource = Drivers.class.getClassLoader () .getResource (& quot; chromedriver.exe & quot;);12System.setProperty (& quot; webdriver.chrome.driver & quot;, resource.getPath ());13retrovert 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 ());
Share this office
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 FreeTest 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