2.1. What you need to know about Groovy

If you already know Java, you have knowledge in three distinct areas:

  • The syntax/keywords of the Java language
  • The Java Development Kit (JDK) that contains many helpful collections and utilities
  • The Java runtime (Java Virtual Machine)

It would be a mistake to think that learning Groovy is like learning a new programming language from scratch. Groovy was designed as a companion to Java.

Groovy offers the productivity boost of a dynamic language (think Python or Ruby) because it doesn’t have as many restrictions as Java. But at the same time, it runs in the familiar JVM and can take advantage of all Java libraries. It completely removes some bulky features of Java and always attempts to minimize boilerplate code by providing only the gist of what you’re doing.

Java is mature as a platform, but as a language, it lags behind in some areas (for example, concurrent facilities or, until recently, functional constructs) that usually are filled by external frameworks. Groovy closes this gap and provides a modern language aimed at productive code sessions in a stable and mature ecosystem of libraries.

Groovy syntax is a superset of Java syntax. Almost all Java code (with some minor exceptions) is valid Groovy code as well. The Groovy Development Kit, or GDK (www.groovy-lang.org/gdk.html), is an enhanced version of the JDK. And most important of all, Groovy runs on the JVM exactly like Java does!

For those reasons, your journey into the magic world of Groovy should be a pleasant adventure in a different yet familiar land. If Java isn’t the only language you speak and you have some experience with other dynamic languages such as Python or Ruby, picking up the basics of Groovy will be an even easier matter.

In a nutshell, Groovy

  • Is a dynamic language (Java is static)
  • Is a strongly typed language (same as Java)
  • Is object-oriented (same as Java)
  • Comes with the GDK (Java has the JDK)
  • Runs on the JVM (same as Java)
  • Favors concise code (Java is considered verbose compared to Groovy)
  • Offers its own libraries (for example, web and object relational frameworks)
  • Can use any existing Java library as-is (Java can also call Groovy code)
  • Has closures (Java 8 has lambda expressions)
  • Supports duck typing[1] (Java has strict inheritance)

    1

    You can learn more about duck typing on Wikipedia at http://en.wikipedia.org/wiki/Duck_typing.

You’ll explore the most important concepts in the next sections and see side-by-side Java and Groovy code where appropriate. I spent a lot of time thinking about which of the Groovy features to showcase in this chapter. I decided to split Groovy features into four categories—essential, useful, advanced, and everything else:

  • Sections 2.1 and 2.2 contain knowledge that I consider essential for Spock tests.
  • Sections 2.3 and 2.4 contain Groovy features that you’ll find useful in your everyday contact with Spock but aren’t otherwise essential.
  • Section 2.5 contains some advanced Groovy features that you may need in your Spock tests in about 20%[2] of cases.

    2

    This number is not scientific in any way.

  • Finally, the rest of Groovy features were left out of this book (even if some of them are essential for writing production code and not unit tests). I invite you to look at the official Groovy web page for more details that I haven’t included here (and there are a lot).
What is the biggest difficulty while learning Groovy as a Java programmer?

If Java is the only language you know, then the biggest barrier (in my opinion) to learning Groovy is Groovy’s dynamic nature. Java provides a direct mapping between a source file and a class. If you know the source code, you know everything there is to know about a class.

In Groovy, a class/object can change during runtime in ways that are impossible in Java. For example, it’s possible to add new methods to a Groovy object (that weren’t in its source code), delegate existing methods to other objects, or even create completely new classes during runtime out of thin air. If you thought that Java introspection was a fancy trick, Groovy has a complete repertoire of magic tricks that will leave your head spinning with all the possibilities.

Fortunately, these Groovy features aren’t essential for unit tests, so you don’t need to be overwhelmed with too much information while you’re learning Spock. If you decide to use Groovy in production code and not just Spock tests, some of its capabilities will certainly amaze you if you’ve never worked with a dynamic language before.

2.1.1. Groovy as a companion to Java

Your first contact with Groovy is probably with the new syntax. Sometimes when I look at Groovy code, I think the syntax is a subset of Java, because Groovy does away with many redundant Java features. Other times I think that Groovy syntax is a superset of Java because it adds capabilities into existing well-known Java structures.

The fact is that Groovy code is more expressive. I promised in the previous chapter that writing your unit tests in Groovy would result in less code than Java. Now it’s time to look at this promise.

How to use the code listings

You can find almost all this book’s code listings at https://github.com/kkapelon/java-testing-with-spock. For brevity, the book sometimes points you to the source code (especially for long listings).

I use the Eclipse IDE in my day-to-day work, as shown in the screenshots throughout the book. You can find specific instructions for installing Spock (including the optional Groovy installation) and the Eclipse IDE (plus some information on alternative IDEs) in appendix A.

Let’s start with the Groovy basics: automatic creation of getters and setters as well as default visibility modifiers, as shown in the next listing.

Listing 2.1. Groovy class conventions

As you can see in this listing,

  • Classes are public by default.
  • Fields are private by default.
  • Getters and setters are automatically created during runtime and thus don’t need to be included in the class declarations.
  • Semicolons are optional and should only be used in case of multiple statements in the same line.[3]

    3

    I’m personally against writing multiple statements in the same line.

These are some of the basic conventions that allow Groovy to cut back on the amount of boilerplate. The biggest gain comes from the removal of getters and setters. You’re free to define a getter/setter if you need to implement it in a different way than the default. Even though the Person.groovy class is written in idiomatic Groovy, the GettersSettersDemo is still Java-like.

You can reduce even further the amount of code by using the Groovy way of field accessing, as shown in the following listing.

Listing 2.2. Groovy field conventions

As seen in this listing, Groovy not only supports the autogeneration of getters and setters, but also allows using only the name of the field instead of the method. The getter or the setter is implicitly called according to the surrounding context. Finally, as a shortcut to System.out.println, Groovy makes available the println method to any object.

You’re not finished yet. You can further refine the code by completely removing the main method and employing Groovy strings to finally reach the state of idiomatic Groovy shown in the next listing.

Listing 2.3. A complete Groovy script

In Groovy, the class name isn’t required to match the name of the source file. The main method is also optional. All code that’s in the top level of the file is treated as a Groovy script. You can completely discard the helper class and use a single Groovy file that holds both the declaration of the class and its usage.

The last piece of the puzzle is the way println is structured. Here I use the interpolation capability of Groovy. The property after the $ is evaluated and inserted directly into the string (which is a Groovy string, as you’ll see later in this chapter). Note that this capability is possible on all strings, not only for those that are printed to the console. Also Groovy makes parentheses optional when calling a method with at least one argument.

At this point, you should already see the benefits of Groovy as far as the amount of code is concerned. The following listing shows a complete Spock test that showcases all Groovy features explained so far. It’s a trivial test that will verify a custom string representation of the Person class.

Listing 2.4. A Spock test using concise Groovy code

Here you define a single Groovy class that contains the Spock test and the class under test for demonstration purposes. The method that’s tested uses string interpolation: the fields are replaced with their value inside the resulting text.

In this Spock test, both the class under test and the unit test itself are written in Groovy. In the next section, you’ll see how Spock tests that are written in Groovy can test Java code.

2.1.2. Accessing Java classes in a Groovy script

In the previous section, you got a small taste of how easy it is to write Groovy code compared to the Java verbose approach. The comparison focused on the syntax of the language. This section compares the way these languages interact during runtime.

Groovy comes with its own compiler (called groovyc) that reads source Groovy files and creates Java bytecode. That’s all you need to know in order to understand how Groovy works with Java. As figure 2.1 shows, Groovy source code is converted to the same bytecode already used by Java files.

Figure 2.1. Both Java and Groovy compile in Java bytecode.

Then the bytecode is loaded in the JVM exactly like any other Java class. The JVM doesn’t care about the original source of a class. It runs each Java or Groovy class in the same way, offering them both the same capabilities and services.

This is an important point to remember. Even though as a developer you may feel that Groovy is much more flexible than Java or that Groovy does too many things behind the scenes, it all boils down to the same bytecode of the same JVM. There isn’t a “Groovy virtual machine.” The Groovy runtime is a single Java archive (JAR) file. Adding Groovy capabilities into an existing Java project is as simple as adding the Groovy JAR into the classpath. Normally, your build system takes care of this inclusion, making the process of running both Groovy and Java code in the same project an effortless task.

After all is said and done, creating and accessing Java objects in Groovy code is exactly the same as in Java code.[4] The following listing shows a Spock test (in Groovy); the class under test is written with Java.

4

It’s also possible to access Groovy code from Java code, but this isn’t needed for Spock testing.

Listing 2.5. Creating and using a Java class from Groovy

That’s the beauty of Java and Groovy integration. Everything works as expected:

  • Groovy code can create Java classes with the new keyword.
  • Groovy code can call Java methods.
  • Groovy classes can extend Java classes.
  • Groovy classes can implement Java interfaces.

It doesn’t get any easier than this!

2.1.3. Declaring variables and methods in Groovy

One of the first questions every Java developer asks when seeing a Spock test is about the use of the def keyword. This keyword is one of the central concepts of Groovy that characterize it as dynamically typed.[5] You can find all the details in the Groovy specification if you feel adventurous, but for the purpose of writing Spock tests, the meaning of def is “I won’t declare a type here; please do it automatically for me.”

5

Or optionally typed, because Groovy still supports the Java way of explicit types.

Thus in Groovy the following listing is possible.

Listing 2.6. Groovy optional typing in variables

As shown in this listing, Groovy supports the usual Java way of declaring things. It also adds its own way, with the type of the object inferred by the context. An alternative way to run Groovy files is using the command line and the groovy executable. The listing results in this output:

> groovy DefDemo.groovy
Susan Ivanova
Is def like Object?

When you’re learning Groovy, it’s easy to think that def is an alias for Object. Even though it might seem to work that way, it doesn’t, and you can find some big differences with Java if you use def in the wrong way in production code. A suggestion that many Groovy developers embrace is to always declare the type of a variable if you know how it will be used. The same suggestion is true for Spock tests, too.

It’s interesting to note that the def keyword can also be applied in methods, as shown in the following listing. This can trim the size of Spock test methods even further (after omitting the visibility modifier).

Listing 2.7. Groovy optional typing in methods

This listing outputs the following:

> groovy DefDemo2.groovy
Ivanova, Susan
Ivanova, Susan (Commander)

Remember that Groovy also supports the Java syntax, so mixing both styles of typing is easy. You can gradually convert to Groovy syntax when you feel comfortable with this notation. Now that you know how the def keyword works, you can see in the following listing how it applies to Spock tests.

Listing 2.8. Using dynamic typing in Spock methods

As shown in this listing, the def keyword is part of standard Groovy. It’s also possible to use full strings for method names. The final result is the Spock DSL for unit tests (and not a standard Groovy feature). I’ve written the same unit test in three possible ways. Even though the syntax is different, they run in exactly the same way as far as Spock is concerned.

2.1.4. Writing less code with Groovy

Groovy still has many tricks under its belt for reducing Java code. For example, the return keyword is also optional. The last evaluated statement in a method is the result of the method in that case. In a similar manner, the def keyword in arguments is also optional. The example from listing 2.7 can be further simplified by using these two rules.

Groovy syntax is indeed a refreshing experience when you come from the Java world. Several things that Java considers essential are simply discarded by Groovy, freeing the programmer from boilerplate code that can be automatically created or understood by the runtime.

While learning Spock, you’ll find several ways to reduce the amount of code, but this doesn’t need to happen right away. My proposal is to follow a gradual learning curve, as shown in figure 2.2.

Figure 2.2. Suggested path for better Spock tests

You already know Java. Your first Spock tests should focus on understanding Spock concepts, so continuing to write “Java-like” Groovy is fine. Once you understand how Spock works, you can apply the shortcuts Groovy offers (as illustrated in the previous sections) to reduce the amount of code and simplify your Spock tests. When you’re confident using Spock, you can apply core Groovy techniques (for example, closures) to write idiomatic Groovy and get completely out of the Java mindset.

A common mistake of Java programmers is writing Spock tests using example code without understanding which feature is Spock-specific and which is offered by Groovy. This can make your Spock journey harder than it should be, so don’t fall into that trap. Make sure that you know how Spock works before applying cool Groovy tricks that dazzle you.

You’ve seen the basic syntax of Groovy and use of the def keyword. Now it’s time to explore Spock asserts.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.182.159