Oliver, I took a look at your tests and they look thorough to me. One recommendation, instead of having 3999 separate selects to test every legal roman numeral, why not just do something like this:
do $$ declare i int; rn text; rn_val int; begin for i in 1..3999 loop rn := trim(to_char(i, 'rn')); rn_val := to_number(rn, 'rn'); if (i <> rn_val) then raise notice 'Mismatch: i=% rn=% rn_val=%', i, rn, rn_val; end if; end loop; raise notice 'Tested roman numerals 1..3999'; end; $$; It's a lot easier to maintain than separate selects.