Skip to content
This repository has been archived by the owner on Mar 12, 2020. It is now read-only.

Commit

Permalink
Add fork option to fix unit tests with serialization and make all cas…
Browse files Browse the repository at this point in the history
…e classes serializable #9

Besides, clear the state machines before and after test suites.
  • Loading branch information
tdauth committed Nov 20, 2018
1 parent 8b34de6 commit a2e5419
Show file tree
Hide file tree
Showing 14 changed files with 53 additions and 38 deletions.
3 changes: 3 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ organization := "retest"

scalaVersion := "2.12.7"

// Fixes serialization issues:
fork := true

// Dependencies to represent the input of states and actions:
libraryDependencies += "de.retest" % "retest-model" % "5.0.0" withSources () withJavadoc ()

Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/de/retest/guistatemachine/api/Action.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ package de.retest.guistatemachine.api
* Selenium action types like `org.openqa.selenium.interactions.Action` should not be used since we require an `equals`
* and `hashCode` method here to use the action as a key for transitions.
*/
case class Action(id: Id)
@SerialVersionUID(1L)
case class Action(id: Id) extends Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ package de.retest.guistatemachine.api
* @param executionCounter The number of times all transitions for the action have been executed from the corresponding state.
* It does not matter to which state. In the legacy code this was stored as `StateGraph.executionCounter`.
*/
case class ActionTransitions(to: Set[State], executionCounter: Int)
@SerialVersionUID(1L)
case class ActionTransitions(to: Set[State], executionCounter: Int) extends Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import de.retest.ui.descriptors.RootElement
/**
* Set of root elements which identifies a state.
*/
case class Descriptors(rootElements: Set[RootElement])
@SerialVersionUID(1L)
case class Descriptors(rootElements: Set[RootElement]) extends Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package de.retest.guistatemachine.api
/**
* This API allows the creation, modification and deletion of state machines ([[GuiStateMachine]]) which are created
* during test generations with the help of Genetic Algorithms.
* To store the state machines permantly, you have to call [[GuiStateMachineApi.save()]] manually.
* To store the state machines permanently, you have to call [[GuiStateMachineApi.save]] manually.
* Otherwise, they will only be stored in the memory.
* [[GuiStateMachineApi.load()]] allows loading state machines from a file.
* [[GuiStateMachineApi.load]] allows loading state machines from a file.
*/
trait GuiStateMachineApi {

Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/de/retest/guistatemachine/api/Id.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.retest.guistatemachine.api

final case class Id(val id: Long) extends Ordered[Id] {
@SerialVersionUID(1L)
case class Id(id: Long) extends Ordered[Id] with Serializable {

override def compare(that: Id): Int = this.id compare that.id
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.io.{FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutp
import de.retest.guistatemachine.api.{GuiStateMachine, GuiStateMachineApi, Id}

object GuiStateMachineApiImpl extends GuiStateMachineApi {
var stateMachines = IdMap[GuiStateMachine]
val stateMachines = IdMap[GuiStateMachine]()

override def createStateMachine(): Id = stateMachines.addNewElement(new GuiStateMachineImpl)

Expand All @@ -18,14 +18,14 @@ object GuiStateMachineApiImpl extends GuiStateMachineApi {
override def save(filePath: String): Unit = {
val oos = new ObjectOutputStream(new FileOutputStream(filePath))
oos.writeObject(stateMachines)
oos.close
oos.close()
}

override def load(filePath: String): Unit = {
clear()
val ois = new ObjectInputStream(new FileInputStream(filePath))
val readStateMachines = ois.readObject.asInstanceOf[IdMap[GuiStateMachine]]
ois.close
stateMachines = readStateMachines
ois.close()
stateMachines.values = readStateMachines.values
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import scala.collection.immutable.{HashMap, HashSet}

@SerialVersionUID(1L)
class GuiStateMachineImpl extends GuiStateMachine with Serializable {
// Make it accessable from the impl package for unit tests.
// Make it accessible from the impl package for unit tests.
private[impl] var states = new HashMap[Descriptors, State]

/**
Expand Down
12 changes: 7 additions & 5 deletions src/main/scala/de/retest/guistatemachine/api/impl/IdMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import scala.collection.immutable.HashMap
*/
@SerialVersionUID(1L)
case class IdMap[T]() extends Serializable {
var values = new HashMap[Id, T]
type HashMapType = HashMap[Id, T]

var values = new HashMapType

/**
* Generates a new ID based on the existing entries.
Expand All @@ -36,13 +38,13 @@ case class IdMap[T]() extends Serializable {
def hasElement(id: Id): Boolean = values.contains(id)

def clear(): Unit = values = new HashMap[Id, T]

override def toString = s"values: $values"
}

object IdMap {
def apply[T](): IdMap[T] = new IdMap[T]

def fromValues[T](v: T*): IdMap[T] = {
val r = IdMap[T]()
def apply[T](v: T*): IdMap[T] = {
val r = new IdMap[T]()
for (e <- v) r.addNewElement(e)
r
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,28 @@ package de.retest.guistatemachine.api.impl
import java.io.File

import de.retest.guistatemachine.api.{AbstractApiSpec, Action, Descriptors, Id}
import org.scalatest.BeforeAndAfterAll

class GuiStateMachineApiImplSpec extends AbstractApiSpec {
class GuiStateMachineApiImplSpec extends AbstractApiSpec with BeforeAndAfterAll {

var stateMachineId = Id(-1)

override def beforeAll = GuiStateMachineApiImpl.clear()

override def afterAll = GuiStateMachineApiImpl.clear()

"GuiStateMachineApi" should {
"create a new state machine" in {
stateMachineId = GuiStateMachineApiImpl.createStateMachine
"create, get and remove a new state machine" in {
stateMachineId = GuiStateMachineApiImpl.createStateMachine()
stateMachineId shouldEqual Id(0)
}

"get a state machine" in {
val stateMachine = GuiStateMachineApiImpl.getStateMachine(stateMachineId)
stateMachine.isDefined shouldBe true
val fsm = stateMachine.get
fsm.getActionExecutionTimes.size shouldEqual 0
fsm.getAllExploredActions.size shouldEqual 0
fsm.getAllNeverExploredActions.size shouldEqual 0
}

"remove a state machine" in {
GuiStateMachineApiImpl.removeStateMachine(stateMachineId) shouldBe true
}

Expand Down Expand Up @@ -53,8 +54,8 @@ class GuiStateMachineApiImplSpec extends AbstractApiSpec {
val finalNeverExploredActions = Set(action0, action1)

// Create the whole state machine:
GuiStateMachineApiImpl.clear
stateMachineId = GuiStateMachineApiImpl.createStateMachine
GuiStateMachineApiImpl.clear()
stateMachineId = GuiStateMachineApiImpl.createStateMachine()
val stateMachine = GuiStateMachineApiImpl.getStateMachine(stateMachineId).get
val initialState = stateMachine.getState(initialDescriptors, initialNeverExploredActions)
val finalState = stateMachine.executeAction(initialState, action0, finalDescriptors, finalNeverExploredActions)
Expand All @@ -66,7 +67,7 @@ class GuiStateMachineApiImplSpec extends AbstractApiSpec {
f.isDirectory shouldEqual false

// Load all state machines:
GuiStateMachineApiImpl.clear
GuiStateMachineApiImpl.clear()
GuiStateMachineApiImpl.load(filePath)

// Verify all loaded state machines:
Expand All @@ -88,7 +89,7 @@ class GuiStateMachineApiImplSpec extends AbstractApiSpec {
val loadedTransition = loadedInitialState.getTransitions(action0)
loadedTransition.executionCounter shouldEqual 1
loadedTransition.to.size shouldEqual 1
loadedTransition.to.toList(0) shouldEqual loadedFinalState
loadedTransition.to.head shouldEqual loadedFinalState
loadedFinalState.getDescriptors shouldEqual finalDescriptors
loadedFinalState.getTransitions.isEmpty shouldEqual true
loadedFinalState.getNeverExploredActions shouldEqual finalNeverExploredActions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class GuiStateMachineImplSpec extends AbstractApiSpec {
"GuiStateMachine" should {
"add two transitions to two new states for the same action and one transition to another state for another action" in {
val initialDescriptors = getDescriptors
val initial = sut.getState(getDescriptors, getNeverExploredActions)
val initial = sut.getState(initialDescriptors, getNeverExploredActions)
sut.getAllExploredActions.size shouldEqual 0
sut.getAllNeverExploredActions.size shouldEqual 2
sut.getActionExecutionTimes.size shouldEqual 0
Expand Down Expand Up @@ -64,8 +64,8 @@ class GuiStateMachineImplSpec extends AbstractApiSpec {

"store a state for the second access" in {
val initialDescriptors = getDescriptors
val initialFromAccess0 = sut.getState(getDescriptors, getNeverExploredActions)
val initialFromAccess1 = sut.getState(getDescriptors, getNeverExploredActions)
val initialFromAccess0 = sut.getState(initialDescriptors, getNeverExploredActions)
val initialFromAccess1 = sut.getState(initialDescriptors, getNeverExploredActions)
initialFromAccess0 shouldEqual initialFromAccess1
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package de.retest.guistatemachine.api.impl

import java.io.{File, FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream}

import org.scalatest.{Matchers, WordSpec}

class IdMapSpec extends WordSpec with Matchers {

"IdMapSpec" should {
"generate new IDs" in {
val map = IdMap[Int]
val map = IdMap[Int]()
val id0 = map.generateId
map.values = map.values + (id0 -> 1)
val id1 = map.generateId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class StateImplSpec extends AbstractApiSpec {
val s0 = new StateImpl(descriptorsA, Set(action0))
val s1 = new StateImpl(descriptorsB, Set(action1))
s0.equals(s1) shouldEqual false
s0.equals(null) shouldEqual false
s0.equals(10) shouldEqual false
s0.hashCode() should not equal s1.hashCode()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package de.retest.guistatemachine.rest

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.{MediaTypes, StatusCodes}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import de.retest.guistatemachine.rest.json.DefaultJsonFormats
import org.scalatest.{Matchers, WordSpec}
import de.retest.guistatemachine.api.impl.GuiStateMachineApiImpl
import de.retest.guistatemachine.api.GuiStateMachine
import de.retest.guistatemachine.api.Id
import de.retest.guistatemachine.api.{GuiStateMachine, Id}
import de.retest.guistatemachine.rest.json.DefaultJsonFormats
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpec}

class RestServiceSpec extends WordSpec with Matchers with ScalatestRouteTest with RestService with DefaultJsonFormats {
class RestServiceSpec extends WordSpec with Matchers with ScalatestRouteTest with RestService with DefaultJsonFormats with BeforeAndAfterAll {

val sut = getRoute(GuiStateMachineApiImpl)

override def beforeAll = GuiStateMachineApiImpl.clear()

override def afterAll = GuiStateMachineApiImpl.clear()

"The service" should {
"show the default text for the GET request with the path /" in {
Get("/") ~> sut ~> check {
Expand Down

0 comments on commit a2e5419

Please sign in to comment.