Unit Testing

Testing

  • How do you know if your code is correct?
  • Submit to AutoLab?
    • Does not exist outside of class
    • Does not exist for your project

Recall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package example
object Conditional {
def computeSize(input: Double): String = {
val large: Double = 60.0
val medium: Double = 30.0
if (input >= large) {
"large"
} else if (input >= medium) {
"medium"
} else {
"small"
}
}
}
  • How do we test this function to verufy that it’s correct?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package example
object Conditional {
def computeSize(input: Double): String = {
val large: Double = 60.0
val medium: Double = 30.0
if (input >= large) {
"large"
} else if (input >= medium) {
"medium"
} else {
"small"
}
}

def main(args: Array[String]): Unit = {
println(computeSize(70.0))
println(computeSize(50.0))
println(computeSize(10.0))
}
}
  • Call the method from main
  • Print the results
  • Manaually verify

What about Large Projects?

  • There may be 100’s of files and 1000’s of methods

  • Any change in a function might break any code

  • Will you manually verify all that code for each change?

  • Unit Testing

    • Automate testing
    • Provide structure to testing

Unit Testing

  • Run a serious of tests on your code
  • If the code is correct, all test should pass
  • If the code is incorrect, at least one test should fail
  • A set of test should test every possible error that could occur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package tests

import org.scalatest._
import example.Conditional

class TestComputeDize extend FunSuite {
test("Doubles are checked for size in each category") {
val largeDouble: Double = 70.0
val mediumDoubleUpperBound: Double = 59.99
val mediumDoubleLowerBound: Double = 30.00
val smallDouble: Double = 10.0

assert(Conditional.computeSize(largeDouble) == "large", largeDouble)
assert(Conditional.computeSize(mediumDoubleUpperBound) == "medium", mediumDoubleUpperBound)
assert(Conditional.computeSize(mediumDoubleLowerBound) == "medium", mediumDoubleLowerBound)
assert(Conditional.computeSize(smallDouble) == "small", smallDouble)
}
}
  • Use Maven to download scalatest
  • Click Maven in the IntelliJ sidebar to interact with pom.xml

Create a new test that will be executed when this file is ran

No main method

FunSuite controls execution instead of main

Is this enough testing?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package tests

import org.scalatest._
import example.Conditional

class TestComputeDize extend FunSuite {

test("Use many test cases for each category"){
// notice largeDouble must be declared with var we change its value
var largeDoubles: List[Double] = List(60.0, 60.01, 70.0, 90.0, 1000.0)
val mediumDoubles: List[Double] = List(59.9, 30.0, 30.01, 40.0, 50.0)
val smallDoubles: List[Double] = List(29.99, 20.0, 10.0, 0.0, -100.0, -1000.0)

largeDoubles = largeDoubles :+ 10000.0 // Example of adding an element to a List

for(largeDouble <- largeDoubles){
assert(Conditional.computeSize(largeDouble) == "large", largeDouble)
}
for(mediumDouble <- mediumDoubles){
assert(Conditional.computeSize(mediumDouble) == "large", mediumDouble)
}
for(smallDouble <- smallDoubles){
assert(Conditional.computeSize(smallDouble) == "large", smallDouble)
}
}
}

Use data structure to run many test cases

Unit Testing Objectives

  • Each homework, and other places in the course, will have objectives that require through testing
  • When these objectives are graded, your test suite is ran:
    • Against your solution
    • Against a correct solution stored on the server
    • Against a variety of incorrect solution stored on the server
  • Your test suite should pass on both your solution and the correct solution
  • Your test suite should fail on all the incorrect solutions

Maven: Dependency Management

  • To run this testing code, we used an external library named Scalatest
    • Scalatest does not come with Scala
    • We must download it before running tests
  • To manage external libraies, we’ll use Maven
    • List all dependancies(libraies)in a file named pom.xml
    • Save pom.xml in the root directory of your project
    • Use Maven to download all dependancies
  • The pom.xml is similar to the requirements.txt file we used in Python

Lecture Question

Method: In a package named “lecture” create an object named “FirstObject” with a metho named “computeShippingCost” that takes a Double representing the weight of a package as a paramater and returns a Double representing the shipping cost of the package.

The shipping cost is ($)5 + 0.25 for each pound over 30.

Unit Testing: In a package named “tests” create a class / file named “UnitTesting” as a test suite that tests the computeShipping Cost method.