PL/SQL Unit TestingCan Be Fun!
with a little helpfrom Ruby
Raimonds Simanovskis
github.com/rsim
@rsim
.com
What is good code?
Correct
Fast enough
Maintainable
Test functionality!
Testperformance!
Test afterchanges!
How is it done?try something...
dbms_output.put_line(...)
it is obvious that there are no bugs
testers should test,that’s their job
What are typical problems?
Trying and not testing
Tests are not repeatable
Manual verification of results
Testing is done too late in development
Types of testsunit tests
integration tests
performance & loadtests
exploratory & usability tests
programmer’sresponsibility
Test Driven Development
Good unit testsAutomatic, run fast
Wide code coverage including edge cases
Repeatable
Independent from execution order
Using real and understandable test data
How to do it when programming in
PL/SQL?
created by Steven Feuerstein, 1999
based on “xUnit”-style frameworks
not maintained anymore :(
Examplesubstring from start until end position
CREATE OR REPLACE FUNCTION betwnstr ( string_in IN VARCHAR2, start_in IN INTEGER, end_in IN INTEGER) RETURN VARCHAR2IS l_start PLS_INTEGER := start_in;BEGIN IF l_start = 0 THEN l_start := 1; END IF;
RETURN (SUBSTR (string_in, l_start, end_in - l_start + 1));END;
TestsCREATE OR REPLACE PACKAGE ut_betwnstr AS
PROCEDURE ut_setup; PROCEDURE ut_teardown;
PROCEDURE ut_normal_usage; PROCEDURE ut_first_index_null;
END ut_betwnstr;
CREATE OR REPLACE PACKAGE BODY ut_betwnstr AS
PROCEDURE ut_setup AS BEGIN NULL; END ut_setup;
PROCEDURE ut_teardown AS BEGIN NULL; END ut_teardown;
PROCEDURE ut_normal_usage AS BEGIN utassert.eq('Normal usage', betwnstr('abcdefg', 2, 5), 'bcde'); END ut_normal_usage;
PROCEDURE ut_first_index_null AS BEGIN utassert.isnull('First index is null', betwnstr('abcdefg', NULL, 5)); END ut_first_index_null;
END ut_betwnstr;
Resultsexec utplsql.test('betwnstr', recompile_in => FALSE);
. > SSSS U U CCC CCC EEEEEEE SSSS SSSS > S S U U C C C C E S S S S > S U U C C C C E S S > S U U C C E S S > SSSS U U C C EEEE SSSS SSSS > S U U C C E S S > S U U C C C C E S S > S S U U C C C C E S S S S > SSSS UUU CCC CCC EEEEEEE SSSS SSSS . SUCCESS: "betwnstr". > Individual Test Case Results:>SUCCESS - betwnstr.UT_FIRST_INDEX_NULL: ISNULL "First index is null" Expected "" and got "">SUCCESS - betwnstr.UT_NORMAL_USAGE: EQ "Normal usage" Expected "cde" and got "cde">>> Errors recorded in utPLSQL Error Log:>> NONE FOUND
Visual testing tools
Quest Code Tester SQL Developer >= 2.1
Why used just by few?Too large / too verbose test code?
Hard to read, too much noise?
Hard to test complex cases?
No best practices how to write tests?
Nobody is using, why should I use?
ruby-plsql-specideal languagefor writing tests
powerful testing toolswith “readable” syntax
library for callingPL/SQL procedures
from Ruby
RSpec
ruby-plsql
Demo
ruby-plsql gemplsql.connect! "hr","hr","xe"
plsql.test_uppercase('xxx') # => "XXX"plsql.test_uppercase(:p_string => 'xxx') # => "XXX"plsql.test_copy("abc", nil, nil) # => { :p_to => "abc", # :p_to_double => "abcabc" }plsql.test_copy(:p_from => "abc", :p_to => nil, :p_to_double => nil) # => { :p_to => "abc", # :p_to_double => "abcabc" }plsql.hr.test_uppercase('xxx') # => "XXX"plsql.test_package.test_uppercase('xxx') # => 'XXX'plsql.hr.test_package.test_uppercase('xxx') # => 'XXX'
plsql.logoff
BenefitsCompact, readable syntax
Powerful features also for complex tests
Best practices from Ruby community
Based on needs from real projects
Open-source – “free as in beer” :)
More information
http://github.com/rsim/ruby-plsql-spec
http://blog.rayapps.com/2010/01/06/screencasts-of-oracle-plsql-unit-testing-with-ruby/
http://blog.rayapps.com/2009/11/27/oracle-plsql-unit-testing-with-ruby/
Top Related