Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ name := "Unit Testing in Scala"

version := "0.1"

scalaVersion := "2.13.1"
scalaVersion := "2.13.1"

libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0" % "test"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/main/scala/com/h2/entities/Dollars.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ object Dollars {
def apply(a: Int): Dollars = new Dollars(a)
}

class Dollars(val amount: Int) extends AnyVal with Ordered[Dollars] {
class Dollars(val amount: Int) extends AnyVal with Ordered[Dollars] {
override def compare(that: Dollars): Int = amount - that.amount

def +(dollars: Dollars): Dollars = new Dollars(amount + dollars.amount)
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/com/h2/services/CustomerService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ trait CustomerService extends CustomersDb {
LocalDate.of(year.toInt, month.toInt, day.toInt)
}

val existingCustomer: Option[Customer] = getExistingCustomer(email)
if (existingCustomer.isDefined) return existingCustomer.get.id

val customer = new Customer(first, last, Email(email), getDateOfBirth)
saveCustomer(customer)
customer.id
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/com/h2/services/Db.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ trait CustomersDb {
def saveCustomer(customer: Customer): Unit = customers += (customer.id -> customer)
def getCustomer(id: UUID): Option[Customer] = customers.get(id)
def numCustomers: Int = customers.size
def getExistingCustomer(email: String): Option[Customer] = {
customers.values.filter(c => c.email.toString == email).lastOption
}
}

trait ProductsDb {
Expand Down
10 changes: 10 additions & 0 deletions src/main/scala/steps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
1) We made sure the project built using 'sbt "runMain BankOfScala"'

2) Add 'libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0" % "test"' to dependencies

3) create src/test/scala/*class*-test.scala

4) - Run tests in Intellij: Add config to run test; click add conf, click '+', scan for Scala test, name the config 'Tests', run all in package, select 'across all modules', use sbt, use "Unit-Testing-In-Scala" module, apply then ok, click play button
- Run tests in terminal: 'sbt', then 'testOnly *DollarSpec'. This is to test the suite (all tests within) 'DollarSpec'.
- Run all tests in terminal: 'sbt', 'test'

7 changes: 7 additions & 0 deletions src/test/scala/HelloWorldFun.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import org.scalatest.funsuite.AnyFunSuite

class HelloWorldFun extends AnyFunSuite{
test("A String 'Hello World' should start with 'Hello'"){
assert("Hello World".startsWith("Hello"))
}
}
14 changes: 14 additions & 0 deletions src/test/scala/HelloWorldSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import org.scalatest.flatspec.AnyFlatSpec

class HelloWorldSpec extends AnyFlatSpec{

// FlatSpec style - the specification text and test are in a flat structure no nesting
behavior of "Hello World"

it should "start with 'Hello'" in {
assert("Hello World".startsWith("Hello"))
}
it should "end with 'World'" in {
assert("Hello World".endsWith("World"))
}
}
73 changes: 73 additions & 0 deletions src/test/scala/assertions/DollarSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package assertions

import com.h2.entities.Dollars
import org.scalatest.flatspec.AnyFlatSpec

class DollarSpec extends AnyFlatSpec{

behavior of "A Dollar"

it should "create a Dollar object for number 10 as input" in {
val tenDollars = Dollars(10)
assert("$10" === tenDollars.toString)
}

it should "correctly identify that $10 > $5" in {
val tenDollars = Dollars(10)
val fiveDollars = Dollars(5)
// we extends the Ordered[Dollars] trait in 'Dollar' class and implemented the 'compare' method
// this allowed us to use the comparison symbols '<' and '>'
assert(tenDollars > fiveDollars)
}

it should "correctly identify that $2 < $10" in {
val tenDollars = Dollars(10)
val twoDollars = Dollars(2)
// we extends the Ordered[Dollars] trait in 'Dollar' class and implemented the 'compare' method
// this allowed us to use the comparison symbols '<' and '>'
assert(twoDollars < tenDollars)
}

it should "correctly add two Dollar amounts" in {
val tenDollars = Dollars(10)
val twoDollars = Dollars(2)
assertResult("$12"){
(twoDollars + tenDollars).toString
}
}

it should "correctly subtract two Dollar amounts" in {
val tenDollars = Dollars(10)
val twoDollars = Dollars(2)
assertResult("$8"){
(tenDollars - twoDollars).toString
}
}

it should "correctly identify that $4 == $4" in {
val fourDollars = Dollars(4)
assertResult(true){
fourDollars === fourDollars
}
}

it should "throw an exception when an invalid integer is provided to create Dollars" in {
// the type of error expected in []
assertThrows[ArithmeticException]{
// the input you expect to cause an exception to be thrown
Dollars(10/0)
}
}

it should "have every dollar more than 0" in {
// assume api call
val dollars: List[Dollars] = List.empty

// PreConditions: The test would pass without this line. We want to cancel it as there are no dollars.
assume(dollars.nonEmpty)

dollars.foreach{ d =>
assert(d.amount > 0)
}
}
}
58 changes: 58 additions & 0 deletions src/test/scala/assertions/EmailSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package assertions

import com.h2.entities.Email
import org.scalatest.flatspec.AnyFlatSpec

class EmailSpec extends AnyFlatSpec{

behavior of "An Email"

it should "return an Email object for a valid string" in {
val email = Email("howdy@google.com")

// you can add a 'clue' as a second arg to 'assert'
assert(email.localPart === "howdy", "expected localPart to be 'howdy'")
assert(email.domain === "google.com")
}

it should "return another Email object for another valid String" in {
assertResult("jim"){
Email("jim@google.com").localPart
}
// if a test is not complete, leave this for colleague.
// also means you can tests/build tests one at at time
// fail("Test all properties of Email object")
}

// if you want a test to be ignored, replace 'it' with 'ignore'
it should "throw an exception when an email does not contain the '@' symbol" in {
withClue("expected IllegalArgumentException since email does not have '@' symbol"){
assertThrows[IllegalArgumentException] {
Email("jim.com")
}
}
}
it should "throw an exception when an email contains more than one '@' symbol" in {
assertThrows[IllegalArgumentException]{
Email("jim@@gmail.com")
}
}

it should "intercept the correct error message when email contains no '@' symbol" in {
val exception = intercept[IllegalArgumentException]{
Email("jim.com")
}
assert(exception.isInstanceOf[IllegalArgumentException])
assert(exception.getMessage.contains("does not contain '@'"))
}

it should "intercept the correct error message when email contains more than one '@' symbol" in {
val exception = intercept[IllegalArgumentException]{
Email("jim@larry@email.com")
}
assert(exception.isInstanceOf[IllegalArgumentException])
assert(exception.getMessage.contains("should not contain '@'"))
}


}
91 changes: 91 additions & 0 deletions src/test/scala/matchers/ContainerSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package matchers

import com.h2.services.Currency

class ContainerSpec extends UnitSpec {

behavior of "Currencies in a wallet"

it should "contain a currency that is added to a List wallet" in {
val oneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"

val wallet = List(oneUsd, twoEuros, tenCad)

wallet should contain (oneUsd)
}

// NEGATIVE CONDITIONAL
it should "not contain a currency that is not added to a List wallet" in {
val oneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"
val tenNzd: Currency = "10 NZD"

val wallet = List(oneUsd, twoEuros, tenCad)

wallet should not contain (tenNzd)
}

it should "contain a currency that is added to a Set wallet" in {
val oneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"

val wallet = Set(oneUsd, twoEuros, tenCad)

wallet should contain (oneUsd)
}

// NEGATIVE CONDITIONAL
it should "not contain a currency that is not added to a Set wallet" in {
val oneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"
val tenNzd: Currency = "10 NZD"

val wallet = Set(oneUsd, twoEuros, tenCad)

wallet should not contain (tenNzd)
}

it should "contain a currency that is added to a Map wallet" in {
val oneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"

val wallet: Map[String, Currency] = Map("USD" -> oneUsd, "EUR" -> twoEuros, "CAD" -> tenCad)

wallet should contain ("USD" -> oneUsd)
}

it should "contain a oneOf 1 USD that is added to a Set wallet" in {
val oneUsd: Currency = "1 USD"
val anotherOneUsd: Currency = "1 USD"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"
val hundredCad: Currency = "100 CAD"

val wallet = Set(oneUsd, anotherOneUsd, twoEuros, tenCad)

// collection should contain exactly 'oneOf' oneUsd OR hundredCad
wallet should contain oneOf (oneUsd, hundredCad)
// for lists this must be 'oneElementOf' instead
wallet should contain oneElementOf List(oneUsd, hundredCad)
}

it should "contain noneOf 1 USD and 100 INR that is added to a Set wallet" in {
val oneUsd: Currency = "1 USD"
val hundredInr: Currency = "100 INR"
val twoEuros: Currency = "2 EUR"
val tenCad: Currency = "10 CAD"
val hundredCad: Currency = "100 CAD"

val wallet: Set[Currency] = Set(twoEuros, twoEuros, tenCad, hundredCad)

wallet should contain noneOf(oneUsd, hundredInr)
// Same thing for Lists
wallet should contain noElementsOf List(oneUsd, hundredInr)
}
}
39 changes: 39 additions & 0 deletions src/test/scala/matchers/EmptinessSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package matchers

import com.h2.services.{Currency, CustomerService}

class EmptinessSpec extends UnitSpec {
val customerService: CustomerService = new CustomerService {}
behavior of "Customer for emptiness"

it should "return empty for customer's last name" in {
val (first, last, email, dateOfBirth) = ("Shane", "", "shane@google.com", "1983/02/01")
val customerId = customerService.createNewCustomer(first, last, email, dateOfBirth)
val customer = customerService.getCustomer(customerId).get

customer.last should be (empty)
// alternative syntax
customer.last shouldBe empty

// NEGATIVE CONDITION
customerId.toString should not be (empty)
}

behavior of "Currencies inside wallet"

it should "be empty when no currencies are added to wallet" in {

val wallet: List[Currency] = List.empty

wallet should be(empty)
}

// NEGATIVE CONDITION
it should "not be empty when currencies are added to wallet" in {

val wallet: List[Currency] = List("1 USD")

wallet should not be(empty)
}

}
Loading