Unit testing tips and tricks database interaction
Download
1 / 29

Unit Testing Tips and Tricks: Database Interaction - PowerPoint PPT Presentation


  • 457 Views
  • Updated On :

Unit Testing Tips and Tricks: Database Interaction . Louis Thomas. Overview. Preaching about TDD What is a Unit Test Common Unit Testing Patterns Unit Testing Database Interactions Acceptance Tests With Databases. Are you test infected? . There are two kinds of people:

Related searches for Unit Testing Tips and Tricks: Database Interaction

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Unit Testing Tips and Tricks: Database Interaction' - lok


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

Overview l.jpg
Overview

Preaching about TDD

What is a Unit Test

Common Unit Testing Patterns

Unit Testing Database Interactions

Acceptance Tests With Databases


Are you test infected l.jpg
Are you test infected?

  • There are two kinds of people:

    • People who don’t like it

      • Can’t be done attitude

    • People who do like it

      • “I think I can” attitude


Test driven development is hard l.jpg
Test Driven Development Is Hard

  • Conceptually, it’s simple!

    (Sure, just like OO is simple…)

  • It’s a learning process. It will be hard at first.

  • Be creative!


I m guilty l.jpg
I’m Guilty…

  • I'm guilty. I am a hack. I am an "impurist". I often don't do "pure" TDD.

  • I find TDD easier to do for some tasks than others. I do whatever I feel like. However, I like what I get with TDD, so I lean towards it

  • Unit tests are good even if you don’t do TDD!


There are many kinds of tests l.jpg
There Are Many Kinds Of Tests

  • Acceptance tests, user test, integration tests, unit tests; black box, white box…

  • All tests have merit if they can detect bugs.

  • Tests only have value if they are run!


Unit tests l.jpg
Unit Tests

  • From developer's point of view.

  • Tests the smallest amount of a system that is interesting.

    Often just one part of one class!

  • Highly automated


Unit test rule of thumb l.jpg
Unit Test Rule Of Thumb

  • If you are having trouble writing a unit test

    or (for those of you who aren't test infected)if it's "impossible" to write a test for your system,

  • You are trying to test to much. Test a smaller chunk.


But how l.jpg
But How?

  • Sometimes objects have complex behaviors, extensive state, and tight relationships. This makes tests difficult:set up is difficult and time consuming, and objects cannot be isolated.

  • (But wait, that’s not right! Right?)


Loosening the coupling l.jpg
Loosening The Coupling

  • Introduce interfaces between complex objects.

  • Create a mock object to stand in for the complex object.

  • Repeat as needed. (Be creative.)


Creating interfaces l.jpg
Creating Interfaces

  • If it's our object, just create an interface!

  • if it's not our object,

    • create a mock that extends the object and overrides all its methods (works sometimes)

    • create an interface anyway and create an adapter for the foreign object

      • Example: WallClock


Example wallclock l.jpg
Example: WallClock

Interface

public interface WallClock {

long getTime();

}

Wrapper for normal system service

public class DefaultWallClock implements WallClock {

public static final WallClock INSTANCE=new DefaultWallClock();

public long getTime() {

return System.currentTimeMillis();

}

}


Mock objects l.jpg
Mock Objects

  • Start out as simple as possible (throw exceptions on all methods).

  • Add recording of incoming method calls

    • - ex: RecordingMockObject, Thumbprinters


Example reportingmockobject l.jpg
Example: ReportingMockObject

public class ReportingMockObject {

StringBuffer m_stringBuffer=new StringBuffer();

//----------------------------------------------------------------

public String getActivityRecordAndReset() {

String sActivityRecord=m_stringBuffer.toString();

m_stringBuffer=new StringBuffer();

return sActivityRecord;

}

//----------------------------------------------------------------

public void recordActivity(String sMessage) {

m_stringBuffer.append(sMessage);

}

}


Example mockclientsession l.jpg
Example: MockClientSession

public class MockClientSession extends ReportingMockObject implements ClientSession {

public MockClientSession() {

}

public void flushOutgoingBuffer() {

recordActivity("fOB");

}

public void setInterval(int nUpdateIntervalMilliseconds) {

recordActivity("sI("+nUpdateIntervalMilliseconds+")");

}

public void notifyNewOutgoingData() {

recordActivity("nNOD");

}

public String getClientName() {

recordActivity("gCN");

return "mockClient";

}

//…

}


Example mockmultitablesessionlistener l.jpg
Example: MockMultiTableSessionListener

public class MockMultiTableSessionListener extends ReportingMockObject implements MultiTableSession.Listener {

public interface Thumbprinter {

String getThumbprint(MultiTableSession.Update update);

String getThumbprint(SessionState sessionState);

}

//################################################################

private final Thumbprinter m_thumbprinter;

//…

public MockMultiTableSessionListener(Thumbprinter thumbprinter) {

m_thumbprinter=thumbprinter;

}

//…

public void sessionStateNotification(SessionState sessionState) {

if (true==m_bLogSessionStateNotification) {

recordActivity("sSN("+m_thumbprinter.getThumbprint(sessionState)+")");

}

}

}


Mock objects cont d l.jpg
Mock Objects, cont’d

  • Add facility for sending back canned responses

    • (ex, setNextReply, setFailOnNextRequest)


Example wallclock18 l.jpg
Example: WallClock

public class MockWallClock implements WallClock {

private long[] m_nextTimes;

private int m_nNextTimeIndex;

public void setNextTime(long nNextTime) {

setNextTimeList(new long[] {nNextTime});

}

public void setNextTimeList(long[] nextTimes) {

Require.neqNull(nextTimes, "nextTimes");

m_nextTimes=nextTimes;

m_nNextTimeIndex=0;

}

public long getTime() {

Assert.neqNull(m_nextTimes, "m_nextTimes");

long nNextTime=m_nextTimes[m_nNextTimeIndex];

m_nNextTimeIndex++;

if (m_nextTimes.length==m_nNextTimeIndex) {

m_nextTimes=null;

}

return nNextTime;

}

}


Mock objects cont d19 l.jpg
Mock Objects, cont’d

  • Do whatever you need

  • Often one mock object will support all tests for a given object, but can create special ones for certain tests

  • Often, one mock object will support tests for many objects that interact with it


Mock object frameworks l.jpg
Mock Object Frameworks

  • EasyMock (http://easymock.org)

  • jMock (http://www.jmock.org/)

  • YMMV!


Object mother l.jpg
Object Mother (?)

  • Sometimes you will need a complex data structure set up. Refactor mercilessly.

  • Especially if you need canned data that is ancillary to the test, it is often worth while to factor creation out into a static method in a util class so you can use it as necessary thereafter.


Testing accessor l.jpg
Testing Accessor

  • Problem: there are private methods you would like to test, or private members you would like to inspect for your test

  • You could make them public, but they really are private

  • Alternative: an inner class! TestingAccessor


Example testingaccessor l.jpg
Example: TestingAccessor

//################################################################

// testing

private WallClock m_wallClock=DefaultWallClock.instance;

private IStepper m_getConStepper=DefaultStepper.instance;

private IStepper m_maintStepper=DefaultStepper.instance;

public class TestingAccessor {

public void setWallClock(WallClock wallClock) {m_wallClock=wallClock;}

public void setGetConStepper(IStepper stepper) {m_getConStepper=stepper;}

public void setMaintStepper(IStepper stepper) {m_maintStepper=stepper;}

public void setNextOverdueConnectionCheck(long tsNextOverdueConnectionCheck)

{m_tsNextOverdueConnectionCheck=tsNextOverdueConnectionCheck;}

public int getAllConnectionsSize() {return m_allConnections.size();}

public int getUnusedConnectionsSize() {return m_unusedConnections.size();}

public int getTotalConnections() {return m_nTotalConnections;}

public void cacheMaintenaceThread() {DBConnectionPool.this.cacheMaintenaceThread();}

public void doNotifyAll() {synchronized (m_oStateLock) {m_oStateLock.notifyAll();}}

}

public TestingAccessor getTestingAccessor() {

return new TestingAccessor();

}


Testing database interactions l.jpg
Testing Database Interactions

  • You should be thankful! All the database classes are interfaces already!

  • Create mocks and away you go

  • Insert / update / delete – easy


Testing database interactions cont d l.jpg
Testing Database Interactions, Cont’d

  • Read – trickier

  • Can use hard coded expectations

  • Mocks will act as factories: statements return record sets

    • load your mock statement with the mock record set to return.

    • load your mock connection with the mock statement to return.

  • Can start out with mocks with hard coded returns, but will probably refactor into more general objects.

  • Ex: Simulated Database Framework


Acceptance tests with databases l.jpg
Acceptance Tests With Databases

  • An acceptance test: Want to test the "whole" app.

  • Good for testing that the database really likes the SQL we hardcoded in the unit tests, and really responds the way we expect


Acceptance tests with databases cont d l.jpg
Acceptance Tests With Databases, Cont’d

  • Big question is, how can we automate? I built up a toolkit as I went.

    • BulkLoadData: reads CSV files and loads data into DB (use Excel to edit)

    • ExecuteSqlScript: processes a text file of SQL commands.

      • Used to create tables, etc.

    • ExecuteDatabaseSetupScript: allows me to write little scripts

      • Knows about 4 commands, including BulkLoadData and ExecuteSqlScript

    • TestResource framework


Acceptance tests with databases cont d28 l.jpg
Acceptance Tests With Databases, Cont’d

  • Big question is, how can we automate? I built up a toolkit as I went.

    • TestResource framework

      • I can define test resources my test needs, setup/teardown methods, and dependencies.

      • Resources will set themselves up from any initial state (ex, delete all rows in table and reload)

  • Now, the acceptance test can just declare all the resources it needs, and framework will set them up. Just needs to mark which resources it dirties, so they can be reset for subsequent tests.


Summary l.jpg
Summary

Preaching about TDD

What is a Unit Test

Common Unit Testing Patterns

Unit Testing Database Interactions

Acceptance Tests With Databases

Questions / demos!


ad