Unroll annotation in Spock Testing framework

Spock is a testing framework for Java and Groovy application. This is a best alternative to Junit. In this post, Let’s see how we can use Unroll annotation of spock framework with an example.

Let’s assume that we have a class called “MathOperation” contains methods to perform arithmetic operations and we have a spock test class to test those methods.

MathOperation.java


public class MathOperation {
    
    private MathOperation(){
        
    }

    public static int sum(int a, int b) {
        return a + b;
    }

    public static int divide(int a, int b) {
        return a / b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static int minus(int a, int b) {
        return a - b;
    }
}


The spock test for testing the ‘sum’ method is as below.


import spock.lang.Specification

class MathOperationSpec extends Specification {

    def "sum of two numbers"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }

When we run this test case, the test run will look like below,

spock-withouunroll

When an error happened, we are not sure which line caused the problem. It will report only the error method but would not give the information about the exact line. The Unroll annotation helps to fix this problem. Unroll annotation has no effect on how the method gets executed but its an alternation in reporting.

Lets rewrite the above test with Unroll annotation as below.


import spock.lang.Specification
import spock.lang.Unroll

class MathOperationSpec extends Specification {

    @Unroll
    def "sum of two numbers #num1 #num2"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }
}

When we run the above one, it will look like below,
spock-withunroll

Advertisements

Scala foldLeft and foldRight functions

In this post, I am going to give some examples which explain how to use foldLeft and foldRight functions.

def foldLeft[B](z: B)(op: (B, A) ⇒ B): B – Applies a binary operator to a start value and all elements of this sequence, going left to right.

def foldRight[B](z: B)(op: (A, B) ⇒ B): B – Applies a binary operator to all elements of this list and a start value, going right to left.

Assume that you have a list and you want to add/multiply all the elements. We can use foldLeft function to do that. The order of traversing a list is from left to right. We can specify the initial value as well. Refer the below example.


object ScalaEx {
  def main(args: Array[String]): Unit = {

    val list = List(10, 10, 5)
    val total = list.foldLeft(1) {
      _ * _
    }
    println(s"Total::$total")

    val names = List("name1", "name2", "name3")
    val allNames = names.foldLeft("")((x, y) => x + " " + y)
    println(s"allNames::$allNames")
  }

}

The output is given below,



Total::500
allNames:: name1 name2 name3

In the above example, we have used foldLeft to multiply the value of a list and then reduce it to a single value and join a list.

The foldRight works the same way but the order of traversing a list is from right to left. Refer the below example to know it.



object ScalaEx {
  def main(args: Array[String]): Unit = {

    val names = List("name1", "name2", "name3")
    val allNamesFR = names.foldRight("")( (elem, acc) => acc + " " + elem )
    println(s"allNames with foldRight::$allNamesFR")

    val allNamesFL = names.foldLeft("")( (acc, elem) => acc + " " + elem )
    println(s"allNames with foldLeft::$allNamesFL")

  }

}


The output is given below,


allNames with foldRight:: name3 name2 name1
allNames with foldLeft:: name1 name2 name3


Scala List

In this post, we are going to see how we can merge two lists, append/prepend an element to a list.

We have various functions available to play with Scala List.

1. ::: or ++ operator to join two lists.
2. :+ and +: operators are used for append/prepend a value to a list(This will return a new list instance)


object Scala {

  def main(args: Array[String]): Unit = {

    //With ::: operator
    val list1 = List(1, 2, 3)
    val list2 = List(4, 5, 6)

    val joinList1 = list1 ::: list2
    println("joinList1::" + joinList1)


    //With ++ operator
    val joinList2 = list1 ++ list2
    println("joinList2::" + joinList2)


    //To append a value to an existing list use :+
    val appendList = list2 :+ 7
    println("appendList::" + appendList)


    //To prepend a value to an existing list
    val prependList =  3 +: list2
    println("prependList::" + prependList)

  }

}


The output is given below,


joinList1::List(1, 2, 3, 4, 5, 6)
joinList2::List(1, 2, 3, 4, 5, 6)
appendList::List(4, 5, 6, 7)
prependList::List(3, 4, 5, 6)

Scala zip/unzip function

Zip function is used to aggregate the contents of two lists into a single list of pairs.

Consider that, we have two lists one contain the list of tasks and another contains list of person names. We want to create another list contains person and task pair. Let see how we can use zip function to do this.

Refer the below example,


object ScalaMain {

  def main(args: Array[String]): Unit = {

    val taskList = List("task1", "task2", "task3")
    val personList = List("Peter", "John", "Patrick")

    val personWithTaskList = personList zip taskList

    personWithTaskList.foreach {
      case (person, task) =>
        println(s"$task is assigned to $person")
    }
  }
}


The output is given below,


task1 is assigned to Peter
task2 is assigned to John
task3 is assigned to Patrick

Unzip function will work as reverse of zip. Refer the below code and its output.



    val unzippedList = personWithTaskList unzip

    println(s"list of persons:${unzippedList._1}")
    println(s"list of tasks:${unzippedList._2}")


Output:


list of persons:List(Peter, John, Patrick)
list of tasks:List(task1, task2, task3)

As the “zip” function creates a pair, it will omit all the unpaired elements. Refer the below example,


object ScalaMain {

  def main(args: Array[String]): Unit = {

    val taskList = List("task1", "task2", "task3")
    val personList = List("Peter", "John", "Patrick", "Joe")

    val personWithTaskList = personList zip taskList

    personWithTaskList.foreach {
      case (person, task) =>
        println(s"$task is assigned to $person")
    }
  }

}


The output of the above program is given below,


task1 is assigned to Peter
task2 is assigned to John
task3 is assigned to Patrick


Spark Cogroup

Spark Cogroup: When called on datasets of type (K, V) and (K, W), returns a dataset of (K, (Iterable, Iterable)) tuples. This operation is also called groupWith.

In this post, we are going to see how we can use Spark Cogroup with an example.

Cogroup can be used to join multiple pair RDD’s. Assume that we have three paid RDD’s such as employeeRdd contains the list of employee objects, addressRdd contains the list of address objects and departmentRdd contains the list of department objects. The key for these Rdd’s are empId. Now we want to join all these Rdd’s with a cogroup command.

case class declaration:


  case class Employee(name: String, empId: String)
  case class Address(streetAddress: String, city: String, zipCode:String, empId: String)
  case class Department(department: String, empId: String)


In the below code, we use the above case classes and a cogroup to join multiple Rdd’s. Here, the departmentRdd does not contain the department details for empId “4” so when we use a cogroup, it returns an empty list for department object and list of address object for empId “4”



 val employeeRdd = sc.parallelize(
        List(
          ("1", Employee(name = "John", empId = "1")),
          ("2", Employee(name = "Peter", empId = "2")),
          ("3", Employee(name = "Adam", empId = "3")),
          ("4", Employee(name = "Wade", empId = "4"))
        ))

      val addressRdd = sc.parallelize(List(
        ("1", Address("Walker St", "Columbus", "43202", "1")),
        ("2", Address("Runner St", "Columbus", "43202", "2")),
        ("3", Address("Long St", "Columbus", "43202", "3")),
        ("4", Address("River St", "Columbus", "43202", "4"))
      ))

      val departmentRdd = sc.parallelize(List(
        ("1", Department("Sales", "1")),
        ("2", Department("Engg", "2")),
        ("3", Department("Marketing", "3"))))

      val employeeDetails = employeeRdd.cogroup(addressRdd, departmentRdd)
        .mapValues { case (employees, addresses, departments) => (employees.head, addresses.toList, departments.toList) }

      employeeDetails.collect().foreach(println)


The output is given below,


(4,(Employee(Wade,4),List(Address(River St,Columbus,43202,4)),List()))
(1,(Employee(John,1),List(Address(Walker St,Columbus,43202,1)),List(Department(Sales,1))))
(2,(Employee(Peter,2),List(Address(Runner St,Columbus,43202,2)),List(Department(Engg,2))))
(3,(Employee(Adam,3),List(Address(Long St,Columbus,43202,3)),List(Department(Marketing,3))))

Angular Pipe

Angular Pipe is used to transform a data/value into desired output in the HTML page.

It takes data as input and transforms the data into expected output.

For example, the syntax of the angular pipe is given below,
{{data | pipe}}

{{Hello world | lowercase }}

There are lots of inbuilt pipes and we can create custom pipes as well.

Assume that you have an array of name and want to join it with a comma symbol. Refer below to know how to do that.

First thing is to create join.ts file and copy the below code in it.

join.ts


import {Pipe, PipeTransform} from '@angular/core'
@Pipe ({
   name : 'join'
})
export class JoinPipe implements PipeTransform {
    public transform(input: string[]): string {
        return input ? input.join(",") : ""
    }
}

Then add the above pipe in app.module.ts as below.


...
import {Join} from "./pipe/join.pipe"
....

    declarations: [Join]

....
export class AppModule {
}

Assume that app.component.ts contains a string array named as “names”. I have not given the app.component.ts file here.

Update the app.componenet.html as below to make use of the join pipe to combine the names.


All names : {{ names | join }

Scala Implicit Function – How to use

In this post, we are going to see how to use Scala Implicit function.

Assume we have a case class “Employee” class which contains name, age, role and location fields and we have a list of Employee case class objects. Lets see how to use Implicit function to find out the employee details by age and also by location.



case class Employee(name: String, age: Int, role: String, location: String)

class EmployeeFunction(employees: List[Employee]) {

    def findEmployeesByRole(role: String): List[Employee] ={
        employees
          .filter(e  => e.role == role)
    }

    def findEmployeesByLocation(location: String): List[Employee] ={
        employees
            .filter(e  => e.location == location)
    }

}

object EmployeeFunction {
    implicit def employeeFunction(employees: List[Employee]):EmployeeFunction = new EmployeeFunction(employees)
}


In the above code, The “EmployeeFunction” contains an implicit function “employeeFunction” defined with “implicit” keyword. So the employee list is implicitly passed to this function.

Now, to use this function in other file, we have to import this function.
Here in the below code, we import the function and then create a list of employee objects and then call “findEmployeesByRole” and “findEmployeesByLocation” methods on it.

Even though the methods findEmployeesByRole” and “findEmployeesByLocation” are not available on the List, it will call the “EmployeeFunction” class methods because of the implicit function.



import EmployeeFunction.employeeFunction

object EmployeeMain {

    def main(args: Array[String]): Unit = {

        val employees = List(Employee(name = "name0", age = 34, role = "programmer", location = "USA"),
                             Employee(name = "name1", age = 34, role = "manager", location = "USA"),
                             Employee(name = "name2", age = 34, role = "analyst", location = "USA"),
                             Employee(name = "name3", age = 33, role = "manager", location = "Canada"),
                             Employee(name = "name4", age = 34, role = "tech lead", location = "India"),
                             Employee(name = "name5", age = 37, role = "manager", location = "India"))

        println("All USA employees are\n" + employees.findEmployeesByLocation("USA"))
        println("All managers are:\n"+employees.findEmployeesByRole("manager"))

    }

}


Refer below the output of the above program



All USA employees are
List(Employee(name0,34,programmer,USA), Employee(name1,34,manager,USA), Employee(name2,34,analyst,USA))
All managers are:
List(Employee(name1,34,manager,USA), Employee(name3,33,manager,Canada), Employee(name5,37,manager,India))