Testing orm based code

1,144 views

Published on

It is always a pain to test code with DB/ORM-dependencies. So, here the rules to ease the process ...

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,144
On SlideShare
0
From Embeds
0
Number of Embeds
156
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Testing orm based code

  1. 1. Testing ORM base codeViktor TurskyiCTO at WebbyLabKiev 2012
  2. 2. Bad NewsORM-based code is databasedependent codeORM framework is a blackbox
  3. 3. Good newsORM is about objects and classesWe can do testing without objectpersistency
  4. 4. Rule 1: No tests for simple classespackage Language;use base qw(Rose::DB::Object);__PACKAGE__->meta->setup( table => languages, columns => [ language_id => { type => varchar, length => 3, not_null => 1 }, name => { type => varchar, length => 64, not_null => 1 }, ], primary_key_columns => [ language_id ],);We do not test ORM framework - it has owntests.
  5. 5. Rule 2: Try inject dependenciespackage VAT;use base qw(Rose::DB::Object);__PACKAGE__->meta->setup( table => vats, columns => [ vat_id => { type => varchar, length => 16, not_null => 1 }, rate => { type => integer, not_null => 1 }, ], primary_key_columns => [vat_id],);sub netto2vat { ... }sub brutto2vat { ... }
  6. 6. Real life VS tests# In real lifemy $vat = VAT->new(vat_id => VAT_20)->load();my $vat_amount = $vat->netto2vat(102.51);...# In testsmy $vat_obj =VAT->new( rate => 20 );is( $vat_obj->brutto2vat(123.01), 20.50, Checking brutto2vat calculations );is( $vat_obj->brutto2vat(456.00), 76.00, Checking brutto2vat calculations );is( $vat_obj->netto2vat(102.51), 20.50, Checking netto2vat calculations );is( $vat_obj->netto2vat(380.00), 76.00, Checking netto2vat calculations );
  7. 7. Real life VS tests (complex)# In real lifemy $fin_event = FinEvent->new( amount => 102.22, # vat_object => ???)->load();my $amount = $fin_event->calculate_vat_amount();# In testsmy $fin_event = FinEvent->new( vat_object => VAT->new( rate=>20 ), amount => 102.22);is( $fin_event->calculate_vat_amount(), 20.44, VAT calculation );
  8. 8. But still a lot of logic requires DBSo, bad news again:In complex operation injection is not alwayssuitable due to complex dependenciesUsing of DBI mock objects is not a good waydue to blackbox nature of the ORM frameworkOne Data Base for whole Model
  9. 9. Simple solutionJust to use the same predefined set of data forall testcountries, users, companies, banks, materials, products, customers, partners,vats, stocks, languages, currencies,currency rates, units... and a lot moreShared set of predefined data worked until westarted work on aggregated reports. Everyreport require a new set of test data whichbreaks other tests data.
  10. 10. Rule 3: Individual test environmentfor each tests setRecreate database for each tests set?=> It takes too much time :(Use embedded DB like SQLite (you can copy file)?=> It requires support of two database schemas :(Manually delete data after each test?=> It requires additional cleanup procedures :(
  11. 11. What we do?Just revert transaction after test :)use Test::More;my $db = Rose::DB->new_or_cached();$db->begin_work();prepare_test_data();do_testing();$db->rollback();
  12. 12. ConclusionsRule 1: No tests for simple classesRule 2: Try inject dependenciesRule 3: Individual test environment for each test
  13. 13. Take a look at our testsmy $t = Test::Project->new(); # starts new transaction$t->standard_setup() ->add_material_from_partner( 1200 ) ->add_service_from_partner( 600, {date=>2011-10-11} ) ->add_material_sale(60, {currency_rate=>800, currency_id=>USD});iterate_test_data( report_a, sub { my $data = shift; my $report = Report::A->new(%{ $data->{input} }); $t->test_correct_report($report, $data);});# on $t->DESTROY() - will revert transaction
  14. 14. Viktor Turskyiviktor@webbylab.com http://koorchik.blogspot.com http://search.cpan.org/~koorchik/ https://github.com/koorchik WebbyLab http://webbylab.com

×