So let me start by saying that I was not a math major, and have never really studied math formally, so if I am way off on some of these concepts, please correct me.
I have been reading recently about using more formal methods like structural inductions and theorems as ways to verify a the correctness of a program. This is something much more prevalent in the functional programming circles and Standard ML seems to be well suited for it. So as I was reading through my Standard ML book, I stumbled upon a number of theorems in regard to lists. It struck me how easily they might be converted into unit tests using Test::More as the logical framework with which to "prove" the theorems. Now, I know that this is by no means a formal proof method and that it might give some staunch math professors indigestion at the thought of it. But to my non-mathematical mind, it seemed like a great way to build some unit tests for testing the integrity of data-structures. But before I get to excited about this, I thought I would put it out for the mathematically inclined folks in the monastery and see what you thought about it.
On the unit-test side of things, I noticed while I was finished writing a set of unit tests for my module Tree::Binary that I found myself creating arbitrary trees to test the values and actions of certain methods. I realized after reading a few theorems of binary trees in the same book I had read the list theorems in, that some of my tests actually looked a little like those theorems. The difference was that instead of testing the equality of two expressions, I was testing an expression against the manually arrived at expected value. This to me seems somewhat fragile, and the idea of writing a test that would prove true in any situation seemed to me to be much more solid.
Now my (likely flawed) understanding of mathematical induction is that give property P you want to prove P(x) for all values of x (or all natural numbers). And with structural induction, the aim is to prove P(x) for all empty and non-empty forms of x. Since testing all possible variances of x would not be possible, and it is not possible to use the reasoning of formal proof methods in unit-tests. My idea of a solution was to use (pseudo) randomly generated structures instead, I don't know if this is way off or not.
Now, at first glance you this might not look like it tests all that much. And you would be right, it doesn't. But this is really just an example, my real question is how valuable this approach to testing might be.
#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; my @list1 = rand_list((rand() * 100)); my @list2 = rand_list((rand() * 100)); my @list3 = rand_list((rand() * 100)); # length(append(L1, L2)) = length(L1) + length(L2) cmp_ok( len(append(@list1, @list2)), '==', (len(@list1) + len(@list2)), '... length(append(L1, L2)) = length(L1) + length(L2)'); # reverse(append(L1, L2)) = append(reverse(L2), reverse(L1)) is_deeply( [ rev(append(@list1, @list2)) ], [ append(rev(@list2), rev(@list1)) ], '... reverse(append(L1, L2)) = append(reverse(L2), reverse(L1))'); # append(L1, append(L2, L3)) = append(append(L1, L2), L3) is_deeply( [ append(@list1, append(@list2, @list3)) ], [ append(append(@list1, @list2), @list3) ], '... append(L1, append(L2, L3)) = append(append(L1, L2), L3)'); # reverse(reverse(L1)) = L1 is_deeply( [ rev(rev(@list1)) ], [ @list1 ], '... reverse(reverse(L1)) = L1'); # --------------------------------------------- sub rand_list { my ($num_items) = @_; return map { (rand() * 100) % $num_items } 0 .. $num_items; } sub len { my @list = @_; return scalar @list; } sub append { my (@combined) = @_; return @combined; } sub rev { my @list = @_; return reverse @list; } 1;
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Theorem proving and Unit testing
by dragonchild (Archbishop) on Aug 25, 2004 at 18:58 UTC | |
by stvn (Monsignor) on Aug 25, 2004 at 21:11 UTC | |
by dragonchild (Archbishop) on Aug 26, 2004 at 12:20 UTC | |
|
Re: Theorem proving and Unit testing
by kvale (Monsignor) on Aug 25, 2004 at 19:15 UTC | |
by stvn (Monsignor) on Aug 25, 2004 at 21:41 UTC | |
by FoxtrotUniform (Prior) on Aug 25, 2004 at 22:15 UTC | |
by stvn (Monsignor) on Aug 25, 2004 at 22:33 UTC | |
by zby (Vicar) on Aug 26, 2004 at 07:51 UTC | |
|
Re: Theorem proving and Unit testing
by sleepingsquirrel (Chaplain) on Aug 25, 2004 at 20:24 UTC | |
by stvn (Monsignor) on Aug 25, 2004 at 22:26 UTC | |
by sleepingsquirrel (Chaplain) on Aug 26, 2004 at 16:59 UTC |