Property-Based Testing

101

🤓 λ 🐘

Hello! I'm beram 👋

🐷 Benjamin Rambaud
🐘 PHP Engineer at @ekino_France

🦄

👉 Property-Based Testing 👈

🤓 You create a new language 🤓

🤓 You create a new language 🤓

How do you test the addition operation❓

x + y

❓

test "add two numbers" {
    assert(1 + 1 === 2);
}

❓

test "add two numbers" {
    assert(1 + 1 === 2);
    assert(2 + 1 === 3);
    assert(7 + 5 === 12);
    assert(300 + 333 === 666);
    assert(1000 + 1 === 1001);
    assert(25253 + 4782 === 30035);
    assert(1.2 + 2.3 === 3.5)
    // etc...
}

Asking a domain expert => a mathematician

  • Commutativity: a + b = b + a

  • Associativity: a + b + c = (a + b) + c = a + (b + c)

  • Identity element is 0: a + 0 = 0 + a = a

test "add two numbers" {
    assert(1 + 1 === 2);
    // etc...
}

@given(a number, b number)
test "addition is commutative" {
    assert(a + b === b + a);
}

@given(a number, b number, c number)
test "addition is associative" {
    assert(a + b + c === (a + b) + c);
    assert((a + b) + c === a + (b + c));
    assert(a + (b + c) === a + b + c);
}

@given(a number)
test "zero is the identity element of the addition" {
    assert(a + 0 === 0 + a);
    assert(a === 0 + a);
    assert(a + 0 === a);
}

That's it 🤓

Asserting that invariants/properties are always true given specific conditions

Common properties 🔍

  • Commutativity
  • Associativity
  • Identity element
  • Successor
  • Reversibility
  • Some things never change
  • Idempotence
  • Structural induction: Solve a smaller problem first
  • Test Oracle: Use an alternate version to check the result

Common properties 🔍

Reversibility

data === decode(encode(data))

Common properties 🔍

Some things never change

an invariant that is preserved after some transformation

length(collection) === length(sort(collection))

Common properties 🔍

Idempotence

given the same input, doing an operation twice is the same as doing it once

Common properties 🔍

Speak to a domain expert to find them 🤓

Is that really it❓

No I lied 😁

  • generate lots of random cases 🥸
  • describe the cases ✍️
  • shrink to find the minimal case it fails 👶

Tooling 🛠

Others

PHP 🐘

Conclusion 🏁

  • Complement all others technics, patterns, etc..
  • Help to prove "it works"
  • Help to find when "it doesn't work"

More readings 🤓

Thanks! Any Questions?

auto

- Drupal: [beram](https://drupal.org/u/beram)

Associativity: the order of operations does not change the result. - Special case for integer - Successor : for any integer `a`, the integer `(a + 1)` is the least integer greater than `a`

shrink: tries to reduce it to a minimal failing subset by removing or simplifying input data that are unneeded to make the test fail.