Jacek Gębal
twitter: @GebalJacek
mail: jgebal@gmail.com
blog: oraclethoughts.com
Principal Software Engineer
@Fidelity Investments - Ireland
co-author & maintainer of: utPLSQL
About me
● Software engineer since ~2000 - mainly Oracle database
● Infected with testing and automation since ~2013
● Key contributor, author and maintainer of utPLSQL v3
● Active developer, learner, testing advocate
Why?
Plan
What?
When?
How?
Why test?
● Check that software “works”
Why do we test?
● Find bugs
● Prove that solution meets requirements and expectations
● Prove that change didn’t break existing functionality
● Document requirements and reveal intention
Automatic test generators
● Find bugs
● Check that software “works”
● Prove that solution meets requirements and
expectations
● Prove that change didn’t break existing
functionality
● Document requirements and reveal intention
● Created from the code
● Created for the code
● Confirm that code “does stuff”
● No confidence that code
“does the right thing”
● No reference to requirements
● Behavior
○ Logic
○ in / out structures
○ State (?)
● Avoid
○ under / over testing
○ unstable tests
○ slow tests
○ testing code you don’t own
What to
test?
● Test early (TDD)
● Test often
● Test automatically (CI/CD)
When to
test?
https://www.google.com/search?q=test+early...
Properties of Unit Tests
● Fast
● Isolated
● Repeatable
● Self-verifying (obvious)
● Thorough & Timely
https://github.com/ghsukumar/.../F.I.R.S.T-Principles-of...
https://pragprog.com/magazines/2012-01/unit-tests-are-first
How to
test?
Test Driven Development
● write a test
● see it fail
● keep it simple
● tests are examples
● tests become
documentation
● get to green fast
● take baby steps
● stuck?
undo and start over
● write only enough
code to pass the test
● remove duplication
(in code and tests)
● rename and clean up
● run tests and stay green
● change implementation,
not behavior
● improve structure
in small steps
RED GREEN
REFACTOR
With TDD you get:
● Fast feedback loop
● Visible & iterative progress
● Code is tested before it exists
● Feeling of accomplishment
with every new test
create room
demo
function - Create room
● Creates a room with given name and returns it’s id
● Throws exception when room name is null
● Throws exception when room exists
Remove room by name
● Removes room that has no content
● Throws exception when room is not empty,
keeps the room and it’s content
● Throws exception when room does not exist
● Throws exception when null room name given
Add room content
● Fails when room does not exist
● Fails when content name is null
● Adds content to existing room
● free & open source
● self tested & compatible with Oracle 11gR2+
● IDE independent
● pure PL/SQL
● tests described only by annotations & expectations
● implements best testing patterns
● easy to Version Control
● transportable
● automatic transaction - no rollback/cleanup needed
● data type - aware comparison (expectations)
Why utPLSQL v3 ?
utPLSQL core
Annotation syntax:
--%suite( description )
--%test( description )
Expectations:
ut.expect( actual_value ).to_( equal( 1 ) );
ut.expect( ‘Chuck’ ).to_equal( ‘Chuck’ );
Running tests:
exec ut.run( [options] );
Annotations
Package:
● --%suite(<description>)
● --%suitepath(<path>)
● --%rollback(auto/manual)
● --%disabled
● --%displayname(<description>)
● --%context(<name>)
● --%endcontext
Test procedure:
● --%test(<description>)
● --%throws(<error>[,...])
● --%beforetest(<proc_name>[,...])
● --%aftertest(<proc_name>[,...])
● --%rollback(auto/manual)
● --%disabled
Procedure:
● --%beforeall, --%afterall
● --%beforeeach, --%aftereach
http://utplsql.org/utPLSQL/latest/userguide/annotations.html
Supported data-types
● clob, blob
● timestamp (with (local) timezone)
● interval (day to second / year to month)
● cursor
● object, nested table, varray
● number (integer)
● varchar2 (char / varchar)
● date
● boolean
Expectations & matchers
● equal( expected )
● be_null / be_not_null
● be_true / be_false
● be_like( mask [, escape_char] )
● match( pattern [, modifiers] )
● contain( expected )
● be_within( offset, expected )
ut.expect( actual ).to_( matcher(param[, param...]) );
ut.expect( actual ).not_to( matcher(param[, param...]) );
● be_between( lower, upper )
● be_greater_than( expected )
● be_less_than( expected )
● be_greater_or_equal( expected )
● be_less_or_equal( expected )
● have_count( count ) / be_empty
Matchers:
Equality rules in tests
ut.expect( 100 ).to_equal( ‘100’ );
ut.expect( ‘abcdef’ ).to_equal( to_clob( ‘abcdef’ ) );
ut.expect( systimestamp ).to_equal( current_timestamp );
ut.expect( sysdate ).to_equal( ‘20-MAR-2018’ );
When it comes to unit testing ...
Data types matter!
Organizing tests with suitepath
● suites hierarchy with suitepath
● parent, siblings, ancestors
● shared beforeall / afterall
● suites isolation / setup scope
demo
Test run options
● default options
● single schema
● single package
● single test
● suite
● multiple schema
● specifying reporter
demo
utplsql-cli
● Windows/Linux/Mac
● real-time reporting
● multi-reporting & saving reports to files
● Oracle client independent
● CI/CD oriented
demo
Integration
● CI/CD servers
○ Jenkins
○ TeamCity
○ Travis
○ other...
● Sonar
○ generic test results
○ code coverage
● Coveralls
○ code coverage
demo
Resources
Downloads: https://github.com/utPLSQL/utPLSQL/releases
Documentation: http://utplsql.org/utPLSQL/
Cheat-sheet: https://www.cheatography.com/jgebal/cheat-sheets/utplsql-v3-1-2/
Source code: https://github.com/utPLSQL/utPLSQL
utPLSQL-cli: https://github.com/utPLSQL/utPLSQL-cli/releases
SQLDeveloper-extension: https://github.com/utPLSQL/utPLSQL-SQLDeveloper/releases
Maven plugin: https://github.com/utPLSQL/utPLSQL-maven-plugin/releases
Twitter: @utplsql
Demo project: https://github.com/utPLSQL/utPLSQL-demo-project
Sonar results: https://sonarcloud.io/dashboard?id=utPLSQL
Coveralls results: https://coveralls.io/github/utPLSQL/utPLSQL
Travis-CI builds: https://travis-ci.org/utPLSQL/utPLSQL

POUG Meetup 1st MArch 2019 - utPLSQL v3 - Testing Framework for PL/SQL

  • 1.
    Jacek Gębal twitter: @GebalJacek mail:[email protected] blog: oraclethoughts.com Principal Software Engineer @Fidelity Investments - Ireland co-author & maintainer of: utPLSQL
  • 2.
    About me ● Softwareengineer since ~2000 - mainly Oracle database ● Infected with testing and automation since ~2013 ● Key contributor, author and maintainer of utPLSQL v3 ● Active developer, learner, testing advocate
  • 3.
  • 4.
  • 5.
    ● Check thatsoftware “works” Why do we test? ● Find bugs ● Prove that solution meets requirements and expectations ● Prove that change didn’t break existing functionality ● Document requirements and reveal intention
  • 6.
    Automatic test generators ●Find bugs ● Check that software “works” ● Prove that solution meets requirements and expectations ● Prove that change didn’t break existing functionality ● Document requirements and reveal intention ● Created from the code ● Created for the code ● Confirm that code “does stuff” ● No confidence that code “does the right thing” ● No reference to requirements
  • 7.
    ● Behavior ○ Logic ○in / out structures ○ State (?) ● Avoid ○ under / over testing ○ unstable tests ○ slow tests ○ testing code you don’t own What to test?
  • 8.
    ● Test early(TDD) ● Test often ● Test automatically (CI/CD) When to test? https://www.google.com/search?q=test+early...
  • 9.
    Properties of UnitTests ● Fast ● Isolated ● Repeatable ● Self-verifying (obvious) ● Thorough & Timely https://github.com/ghsukumar/.../F.I.R.S.T-Principles-of... https://pragprog.com/magazines/2012-01/unit-tests-are-first How to test?
  • 10.
    Test Driven Development ●write a test ● see it fail ● keep it simple ● tests are examples ● tests become documentation ● get to green fast ● take baby steps ● stuck? undo and start over ● write only enough code to pass the test ● remove duplication (in code and tests) ● rename and clean up ● run tests and stay green ● change implementation, not behavior ● improve structure in small steps RED GREEN REFACTOR With TDD you get: ● Fast feedback loop ● Visible & iterative progress ● Code is tested before it exists ● Feeling of accomplishment with every new test
  • 11.
  • 12.
    function - Createroom ● Creates a room with given name and returns it’s id ● Throws exception when room name is null ● Throws exception when room exists
  • 13.
    Remove room byname ● Removes room that has no content ● Throws exception when room is not empty, keeps the room and it’s content ● Throws exception when room does not exist ● Throws exception when null room name given
  • 14.
    Add room content ●Fails when room does not exist ● Fails when content name is null ● Adds content to existing room
  • 15.
    ● free &open source ● self tested & compatible with Oracle 11gR2+ ● IDE independent ● pure PL/SQL ● tests described only by annotations & expectations ● implements best testing patterns ● easy to Version Control ● transportable ● automatic transaction - no rollback/cleanup needed ● data type - aware comparison (expectations) Why utPLSQL v3 ?
  • 16.
    utPLSQL core Annotation syntax: --%suite(description ) --%test( description ) Expectations: ut.expect( actual_value ).to_( equal( 1 ) ); ut.expect( ‘Chuck’ ).to_equal( ‘Chuck’ ); Running tests: exec ut.run( [options] );
  • 17.
    Annotations Package: ● --%suite(<description>) ● --%suitepath(<path>) ●--%rollback(auto/manual) ● --%disabled ● --%displayname(<description>) ● --%context(<name>) ● --%endcontext Test procedure: ● --%test(<description>) ● --%throws(<error>[,...]) ● --%beforetest(<proc_name>[,...]) ● --%aftertest(<proc_name>[,...]) ● --%rollback(auto/manual) ● --%disabled Procedure: ● --%beforeall, --%afterall ● --%beforeeach, --%aftereach http://utplsql.org/utPLSQL/latest/userguide/annotations.html
  • 18.
    Supported data-types ● clob,blob ● timestamp (with (local) timezone) ● interval (day to second / year to month) ● cursor ● object, nested table, varray ● number (integer) ● varchar2 (char / varchar) ● date ● boolean
  • 19.
    Expectations & matchers ●equal( expected ) ● be_null / be_not_null ● be_true / be_false ● be_like( mask [, escape_char] ) ● match( pattern [, modifiers] ) ● contain( expected ) ● be_within( offset, expected ) ut.expect( actual ).to_( matcher(param[, param...]) ); ut.expect( actual ).not_to( matcher(param[, param...]) ); ● be_between( lower, upper ) ● be_greater_than( expected ) ● be_less_than( expected ) ● be_greater_or_equal( expected ) ● be_less_or_equal( expected ) ● have_count( count ) / be_empty Matchers:
  • 20.
    Equality rules intests ut.expect( 100 ).to_equal( ‘100’ ); ut.expect( ‘abcdef’ ).to_equal( to_clob( ‘abcdef’ ) ); ut.expect( systimestamp ).to_equal( current_timestamp ); ut.expect( sysdate ).to_equal( ‘20-MAR-2018’ ); When it comes to unit testing ... Data types matter!
  • 21.
    Organizing tests withsuitepath ● suites hierarchy with suitepath ● parent, siblings, ancestors ● shared beforeall / afterall ● suites isolation / setup scope
  • 22.
  • 23.
    Test run options ●default options ● single schema ● single package ● single test ● suite ● multiple schema ● specifying reporter
  • 24.
  • 25.
    utplsql-cli ● Windows/Linux/Mac ● real-timereporting ● multi-reporting & saving reports to files ● Oracle client independent ● CI/CD oriented
  • 26.
  • 27.
    Integration ● CI/CD servers ○Jenkins ○ TeamCity ○ Travis ○ other... ● Sonar ○ generic test results ○ code coverage ● Coveralls ○ code coverage
  • 28.
  • 29.
    Resources Downloads: https://github.com/utPLSQL/utPLSQL/releases Documentation: http://utplsql.org/utPLSQL/ Cheat-sheet:https://www.cheatography.com/jgebal/cheat-sheets/utplsql-v3-1-2/ Source code: https://github.com/utPLSQL/utPLSQL utPLSQL-cli: https://github.com/utPLSQL/utPLSQL-cli/releases SQLDeveloper-extension: https://github.com/utPLSQL/utPLSQL-SQLDeveloper/releases Maven plugin: https://github.com/utPLSQL/utPLSQL-maven-plugin/releases Twitter: @utplsql Demo project: https://github.com/utPLSQL/utPLSQL-demo-project Sonar results: https://sonarcloud.io/dashboard?id=utPLSQL Coveralls results: https://coveralls.io/github/utPLSQL/utPLSQL Travis-CI builds: https://travis-ci.org/utPLSQL/utPLSQL