What is Zucchini?
Zucchini is a new testing framework that uses a BDD-style domain-specific language (DSL). One of its focus areas is simplifying acceptance tests written with Selenium. It is not a replacement for JBehave or the Robot Framework, as you will see later on. This guide will give you a glimpse of Zucchini’s concepts by describing an example step by step.
Your First Zucchini Test
We are starting with this simple test class:
1public class GettingStarted extends CommonStatements {
2 @Test
3 public void testCodecentricSearch() {
4 given("I am on codecentric.de")
5 .when("I type \"codecentric\" into the search box")
6 .andWhen("I submit the search")
7 .then("I see \"codecentric\" on the page")
8 .end();
9 }
10}
This looks pretty easy, doesn’t it? But let’s examine this test for a moment:
- This is obviously some kind of test.
@Test
suggests that this is a JUnit test, and that is indeed correct. - It seems like there is some kind of domain-specific language involved:
given().when().andWhen().then().end()
. "I am on codecentric.de"
looks like some kind of initial situation."I type \"codecentric\" into the search box"
and"I submit the search box"
look like interactions that a user has with a website."I see \"codecentric\" on the page"
looks like an expectation.
If you’ve made it so far, you already know 90% of the important stuff. But wait, we missed something, didn’t we? How does the test know what to do with these statements? Is there a complex language I have to learn before? And what is this CommonStatements
class doing there? Okay, to be honest: I have held back some information. First of all, no, you don’t have to learn a new language. The statements in this test are placeholders for instructions that I will show you in a moment. And yes, CommonStatements
plays a big role. But most importantly: This is a real test and it works perfectly. It will do what you expect it will do and there is missing in this class. The next section will describe the magic behind those statements.
The CommonStatements
class
Magic
The previous section contained a simple test that navigates to codecentric.de, types “codecentric” into the search box, submits the search box and expects “codecentric” to be somewhere on the page – for example, as part of search results – afterwards. There seemed to be some magic involved since we have already ruled out that there is a complex language you have to learn. So what is the magic inside CommonStatements
? I am sorry to disappoint you but there is no magic at all. This is most of the part that I have held back before:
1public class CommonStatements {
2 @Rule
3 public WebFactRule onCodecentricRule = new WebFactRule(
4 "I am on codecentric.de",
5 onPage(url("http://www.codecentric.de"))
6 );
7
8 @Rule
9 public WebStepRule searchCodecentricRule = new WebStepRule(
10 "I type \"codecentric\" into the search box",
11 type("codecentric").into(By.name("s"))
12 );
13
14 @Rule
15 public WebStepRule submitSearchRule = new WebStepRule(
16 "I submit the search",
17 submit(By.name("s"))
18 );
19
20 @Rule
21 public WebResultRule seeCodecentricOnPageRule = new WebResultRule(
22 "I see \"codecentric\" on the page",
23 see("codecentric")
24 );
25
26 @Rule
27 public WebDriverExecutorRule webDriverExecutorRule = new WebDriverExecutorRule(
28 new ChromeDriverProvider()
29 );
30}
Okay, now I’ve lost you. Let’s take baby steps towards becoming a Zucchini master.
Facts
We will start with the following code snippet as a first step:
1@Rule 2public WebFactRule onCodecentricRule = new WebFactRule( 3 "I am on codecentric.de", 4 onPage(url("http://www.codecentric.de")) 5);
At first, you will notice that the statement that we have seen in our test case is part of a JUnit @Rule
. I will not talk about JUnit @Rule
s here. If you don’t already know about this concept, you might want to go to the documentation before you continue.
The second part of the so called WebFactRule
is onPage(url("http://www.codecentric.de"))
. Both, onPage()
and url()
are statically imported methods.
onPage()
returns a WebFact
. Basically, a fact is something you expect to be part of the initial state of a test. Actually, you don’t want to test facts. You take them for granted. Of course, Zucchini will detect if facts are broken and your test will fail if they are. If you have worked with Behavior Driven Development (BDD) before, you’re already familiar with Given, When, and Then. Zucchini calls atomic statements describing the initial state (Given) facts. Now, onPage()
does not return Fact
but WebFact
. Web facts are specialized facts for web testing purposes. WebFact
is just the interface for all types of web-specialized facts. The actual type of the object returned by onPage()
is OnPageFact
. All fact implementations describe how Zucchini can establish them. The OnPageFact
knows how to open a specific page.
So, why do you need url()
, you might ask. OnPageFact
is more powerful than you need to know for the moment (in case you are curious: it supports Page Objects ). The OnPageFact
does not work on URLs directly but on something like a wrapper. For the sake of simplicity, let’s say url()
takes a URL and wraps it in an object. I guess, we can take a step back and look at the previous code snippet again:
- The
WebFactRule
is a JUnit@Rule
that registers a fact. - The example above uses
"I am on codecentric.de"
as a name – no magic involved! - The fact of this example is able to open http://www.codecentric.de in a browser.
Steps
While growing up and learning more, baby steps become bigger. So let’s take a bigger code snippet:
1@Rule 2public WebStepRule searchCodecentricRule = new WebStepRule( 3 "I type \"codecentric\" into the search box", 4 type("codecentric").into(By.name("s")) 5); 6 7@Rule 8public WebStepRule submitSearchRule = new WebStepRule( 9 "I submit the search", 10 submit(By.name("s")) 11);
We have seen facts in the previous section. Now, we will introduce steps. While facts describe the initial state of the test, steps describe what you want to do once the initial state has been established.
What’s new? Actually, not much. Zucchini provides many useful methods that you can import statically to interact with pages, for example:
type(keys)
types the givenkeys
(text or a key combination) on the page,type(keys).into(element)
types the givenkeys
into anelement
(e.g. a text input, text area, WYSIWYG editor, …),select(element).index(index)
selects the option with theindex
of a selectelement
,click(element)
clicks on anelement
,submit(element)
submits anelement
, and many more.
Most of the web steps work on elements. These elements are described using Selenium’s By
, for example:
By.id("html-element-id")
describes the HTML element with the id attribute valuehtml-element-id
,By.name("input-name")
describes the HTML element with the name attribute valueinput-name
,
Note: It is possible to create By
locators that locate multiple elements. That’s perfectly fine. Sometimes you want to do something with multiple elements.
For more information on locating elements, please take a look at the Selenium WebDriver documentation.
By now, you should have deciphered the two rules above. However, I will summarize what you most likely already know:
- Two new steps have been registered.
- The first step is called
"I type \"codecentric\" into the search box"
and it simply types the text “codecentric” into a search box. - The second step is called
"I submit the search"
and it simply submits the search box (similar to hitting enter while still focussing the box).
Results
We are getting close to the end of this guide. By now, you should have figured out how to register facts that define the initial state and steps that describe how you want to interact with a page. This section will show you how you can check for page characteristics.
1@Rule 2public WebResultRule seeCodecentricOnPageRule = new WebResultRule( 3 "I see \"codecentric\" on the page", 4 see("codecentric") 5);
A WebResult
is a web-specific Result
that checks whether the page state looks like you’d expect it to look. Zucchini provides some basic implementations, for example:
see(text)
checks whether thetext
is present on the page,input(element).isDisabled()
checks whether theelement
is disabled.
The @Rule
above can be described as follows:
- A new result is registered.
- The new result is called
"I see \"codecentric\" on the page"
. - The result expects that “codecentric” is shown.
Now you know what facts, steps, and results are and you know how you can define them. Since Zucchini uses plain Java, you will be able to use all of your IDE’s auto-completion features. You don’t need an additional plug-in for your IDE or additional IDE configuration.
Executing Tests
The last part of the CommonStatements
class is this:
1@Rule 2public WebDriverExecutorRule webDriverExecutorRule = new WebDriverExecutorRule( 3 new ChromeDriverProvider() 4);
This guide focusses on Zucchini’s web components. You can use Zucchini for other types of tests but that is a whole other story. I tell you this because different types of tests require different types of Executor
s.
The @Rule
above registers a web-specific Executor
that uses the Selenium WebDriver API internally. Selenium can run in multiple browsers so we need to tell the executor which browser to use. This example uses Chrome. You might want to use HtmlUnit instead for headless testing. I’ll leave you to it.
Dig Deeper
This short guide introduced parts of Zucchini which is a lean testing framework that uses a BDD-style DSL. You have learned how to write simple Zucchini web tests and I have shown you the basic concepts behind Zucchini. Here are some suggestions in case you want to dig deeper into Zucchini:
- Browse through the GitHub repository .
- Explore the example project that contains many other aspects.
- Take a look at pre-defined facts , steps , and results .
- Write your own tests.
- Help improving Zucchini .
More articles
fromAlexander Rose
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Alexander Rose
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.