Performance testing with Gatling – Scala fundamentals

Last Updated on by

Post summary: Tutorial that covers basic Scala functionalities that may be needed during Gatling automation.

Current post is part of Performance testing with Gatling series in which Gatling performance testing tool is explained in details.

You need to have basic Java knowledge as this tutorial in most of the cases compares Scala with Java.

General concepts

In order to use Scala, its compiler needs to be installed from Scala home page. Scala source code is compiled to Java Byte Code and is run on Java Virtual Machine.

Scala is an object-oriented functional programming language. Everything in Scala is an object. There are no primitive types as in Java, those are represented by objects. Even functions are also objects.

There is very good interoperability with Java and Java code can be used inside Scala. Java object from Java classes can be created, also static methods in Java classes can be called.

Syntax

Scala syntax is pretty much the same as in Java. Although Scala is statically typed (checks are done at compile time) in most of the cases you do not need to explicitly specify variable type, Scala compiler knows it.

Scala is case-sensitive, class names are CamelCase with the first letter being capital, method names are also camel case starting with a lower case letter.

Semicolon “;” is not mandatory at the end of the line is it has only one expression. In case of more expressions on one line then is mandatory to separate each expression with a semicolon.

Classes and packages

The class file name should be with the same name as the class itself.

Import all classes from a package is done with an underscore:

import io.gatling.core.Predef._

Import of several classes from a package is done with curly brackets:

import org.joda.time.format.{DateTimeFormat, DateTimeFormatter}

Data types

As stated above everything is Scala is an object. There are no primitive types. Those are represented by objects:

  • Byte – 8 bit signed value. Range from -128 to 127
  • Short – 16 bit signed value. Range -32768 to 32767
  • Int – 32 bit signed value. Range -2147483648 to 2147483647
  • Long – 64 bit signed value. -9223372036854775808 to 9223372036854775807
  • Float – 32 bit IEEE 754 single-precision float
  • Double – 64 bit IEEE 754 double-precision float
  • Char – 16 bit unsigned Unicode character. Range from U+0000 to U+FFFF
  • String – a sequence of Chars
  • Boolean – either the literal true or the literal false
  • Unit – corresponds to no value
  • Null – null or empty reference
  • Nothing – the subtype of every other type; includes no values
  • Any – the supertype of any type; any object is of type Any
  • AnyRef – the supertype of any reference type

Strings and Arrays

Strings and arrays are very similar to Java ones. In Scala is possible to define multi-line string literal. This is done with three quotes: “””This is text

split into two lines”””

Variables

Variable declaration is done with the following format:

val or val VariableName : DataType [= Initial Value]

Example is: var answer : Int = 42. This is the full declaration. In most cases you do not need to provide data type, so above can be shortened to: var answer = 42.

With var you define a variable that is going to change its value. On the other hand, val keyword is used for defining variables that will never change, constants, like final in Java.

Access modifiers

Access modifiers are public, private and protected. There is no explicit keyword public though. If no modifier is used then access level is considered public.

private and protected can be defined for a specific scope.

private[com.automationrhpasody.gatling]

In the example above, field, method or class that this modifier is applied to is considered private for all the world, except for classes in package com.automationrhpasody.gatling. The scope can be a single class or singleton object (more about those will follow).

Operators

Operators are very similar to Java. Those are:

  • Arithmetic Operators (+, -, *, /, %)
  • Relational Operators (==, !=, >, <, >=, <=)
  • Logical Operators (&&, |, !)
  • Bitwise Operators (&, |, ^, ~, <<, >>, >>>)
  • Assignment Operators (=, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=)

Unlike Java there are no ++ and — operators. This is because everything in Scala is object and default data types are immutable objects. So modifications on current object are not possible, new object is created instead, so it is not possible to have ++ and — operations.

Conditional statements

A conditional statement is if/else same as in Java:

if (condition) {
	statement
}

if (condition) {
	statement1
} else {
	statement2
}

if (condition1) {
	statement1
} else if (condition2) {
	statement2
} else {
	statement3
}

Loop statements

Loop statements are for, while, do/while. For statement is very specific, the easiest way to use it is with Ranges:

for (i <- 1 until 10) {
	println("i=" + i)
}

The code above will print values from 1 to 9. Operator <- is called generator as it generating the individual values from the range. 1 until 10 is the actual range. This is the number from 1 to 9, 10 is not included. If you want the last value included use to: 1 to 10.

It is possible to put some conditional statement in the for loop with if clause:

for (i <- 1 until 10; if i >= 3 && i <= 6) {
	println("i=" + i)
}

The code above will print values 3, 4, 5 and 6. Only those are >= 3 and <= 6 from the whole range.

Nested for loops are pretty easy in Scala and not that apparent, so it is easy to get into performance issues:

for (i <- 1 until 5; j <- 1 to 3) {
	println("i=" + i)
	println("j=" + j)
}

The code above is equal to Java code:

for (int i = 0; i < 5; i++) {
	for (int j = 0; j <= 3; j++) {
		System.out.println("i=" + i);
		System.out.println("j=" + j);
	}
}

For loop can also be used with collections:

val daysOfWeek = List("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
for (str <- daysOfWeek) {
	println("day=" + str);
}

You can also iterate Java collections, but first, they need to be converted by classes in scala.collection.JavaConversions package. Below is example iterating Java’s System Properties:

import scala.collection.JavaConversions._

for (key <- System.getProperties.keySet().iterator.toIterator) {
	println("Key=" + key + ", Value=" + System.getProperty(key.toString))
}

Loop statements while and do/while as in Java:

while (condition) {
	statement
}

do {
	statement
} while (condition)

Methods and functions

Scala has both functions and methods. This is a group of statements and conditions that perform a task and can return a result. Difference between those is that method can be defined only inside a class. A function can be defined anywhere in the code. This is an object that can be assigned to a variable. Functions and method names in Scala can contain special characters such as +, -, &, ~, etc.

A function definition is:

def functionName ([list of parameters]) : [return type] = {
	function body
	[return] [expr]
}

Data in [] are optional. The return type is any valid Scala type. If nothing is to be returned then Unit is returned, this is as void methods in Java. As you can notice even return statement, in the end, is not mandatory and can be omitted, then the function will return the statement that comes last.

def sum(a: Int, b: Int): Int = {
	a + b
}

Function/method above sums two Integer values and returns the result of the sum.

A function is called the same way as in Java:

[object.]functionName([list of parameters])

Scala is function based language, so there are many many things that can be done with functions. More you can read on Scala functions in Tutorialspoint.

Collections

A collection is a group of objects. Scala API has a rich set of collections. By default collections in Scala are immutable. This means current collection object cannot be changed, if you do some change on a collection this results in the creation of new collection with desired changes applied in it. This is made for thread safety. There are also mutable collections. They can be found in scala.collection.mutable package.

  • Lists – lists are very similar to arrays, you have elements in sequential order that can be accessed.
  • Sets – collection of unique elements, there are no duplicates.
  • Maps – a collection of key/value pairs. Values are retrieved based on their unique key.
  • Tuples – combines several elements together so they can be considered one object.
  • Iterators – not actually a collection, but a way to access elements from a collection one by one.

More about Scala collections can be found in Scala collections in Tutorialspoint.

Classes, objects

A class is a blueprint for objects. A class is like a cookie cutter. Objects are the cookies. Objects are created with keyword new. A class name is a class constructor taking different arguments. You can pass parameters to it. A class can have several constructors. The restriction is that each constructor should call on its first line some other constructor. Eventually, the main constructor in the class name will get called. Classes can be extended similarly to Java.

class Car(isStarted: Boolean) {
	var _isStarted: Boolean = isStarted
	var _speed: Int = 0

	def this() = this(true)

	def start(): Unit = {
		_isStarted = true
		println("Car is started: " + _isStarted)
	}

	def drive(speed: Int): Unit = {
		_speed = speed
		if (_isStarted) {
			println("Car moving with speed: " + _speed)
		} else {
			println("Car is not started!")
		}
	}
}

Singleton objects

In Scala, there is no definition of static methods or fields. In order to accomplish similar functionality, you can use singleton objects, classes with only one instance defined with object keyword.

object UseThatCar {
	def main(args: Array[String]) {
		val car1 = new Car(false)
		car1.drive(50)

		val car2 = new Car()
		car2.drive(45)
	}
}

Resources

I do not tend to be Scala expert. I know little but enough to make Gatling performance testing. So I have used other network resources to build this post. A very good tutorial is Scala in Tutorialspoint. Another interesting post is The 10 Most Annoying Things Coming Back to Java After Some Days of Scala.

Conclusion

People that have worked with Scala really love it. It is made for performance and scalability. Because everything is object and default types are immutable objects Scala is much more thread safe than Java. Functions can be defined anywhere and do everything you want, so you can do almost everything with just functions if you like. Although it is that good Scala is compiled to Byte Code and run on Java Virtual Machine, so limitations applicable to JVM are applicable to Scala executable code. No matter if you like it or not, you have to learn basics of Scala as Gatling is written in Scala and in order to do performance testing with it you have to know Scala fundamentals.

Related Posts