PL/SQL Unit Testing Can Be Fun!

Post on 18-May-2015

13,136 views 3 download

Tags:

transcript

PL/SQL Unit TestingCan Be Fun!

with a little helpfrom Ruby

github.com/rsim

Raimonds Simanovskis

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 & integrationtests

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” :)

JRuby meetupTuesday, September 21

@ Engine Yard500 3rd Street, Suite 510

5:30 - 7:00 Networking + beer + food7:00 - 8:00 Lightning talks