CMSC330

Testing

Testing

Testing
Unit Testing
Property Based Testing

Testing

Testing

Test: routine that checks the operation of your code

Why Test

  • Save Time
  • Allows for Expansion
  • Increases Trust
  • Helps Collaboration

Things to Test

  • Branch Coverage
  • Statement Coverage

Types of Tests

  • White Box
  • Black Box
  • Isolated
  • Integration
  • Functional

Unit Testing

Unit test: testing units of a program


let rec three_in_a_row lst = match lst with
[] -> false
|[_] -> false
|[_;_] -> false
|[a;b;c] -> a = b && b = c
|a::b::c::t if a = b && b = c then true else three_in_a_row t;;
          

We can test in utop:


three_in_a_row [1;2;2;2;3;4]
three_in_a_row [1;2;2;3;2;4]
three_in_a_row [1]
          

We can test in utop:


three_in_a_row [1;2;2;2;3;4]
three_in_a_row [1;2;2;3;2;4]
three_in_a_row [1]
          

Or use a Testing Framework (OUnit, JUnit, Minitest,pytest,cargo)


let tests = "Testing for tiar" >::: [
  "valid" >:: (fun _ -> assert_equal true (three_in_a_row [1;2;2;2;3;4]));
  "seperated" >:: (fun _ -> assert_equal false (three_in_a_row [1;2;2;3;2;4]));
  "not enough" >:: (fun _ -> assert_equal false (three_in_a_row [1]));
  ]
          

let tests = "Testing for tiar" >::: [
  "valid" >:: (fun _ -> assert_equal true (three_in_a_row [1;2;2;2;3;4]));
  "seperated" >:: (fun _ -> assert_equal false (three_in_a_row [1;2;2;3;2;4]));
  "not enough" >:: (fun _ -> assert_equal false (three_in_a_row [1]));
  ]
          

There are some limitations

  • Need to think of things to check
  • Writing becomes O(n)
  • Edge Cases hard to think of

Enter Property Based Testing

Property Based Testing

Enter Property Based Testing

Property Based Testing (PBT): testing if code satisfies properties

Property: Something we expect to be true

Property: Something we expect to be true

Some examples

  • Even integers are divisible by 2
  • Reversing a list twice should be have no effect
  • Adding an element to a list, then looking up that element should succeed
  • Deleting an element to a list, then looking up that element should fail
  • Sum of a list should be >= largest element
  • A sorted list should have smallest value at index 0
  • Even integers are divisible by 2

Once we have a property, we need to express our property in terms of code


fun x -> is_even (x*2) = true 
          

Then use a pbt framework (like qcheck)


let even_test = Test.make (int) (fun x -> is_even (x*2) = true) in
QCheck_runner.run_tests [even_test]
          

Limitations on PBT

  • Not everything can be a property
  • Conversion of property to code can be incorrect
  • Thinking of properties is also hard