Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 General SQL Server Forums
 Database Design and Application Architecture
 TTD and Unit Testing in the database

Author  Topic 

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2011-05-31 : 06:53:57
Hello everyone. Not been posting in a while because I've been busy with new work.

I'd like to ask the community about what kind of test frameworks you all use for database development.... I'm in the middle of developing a star schema and associated aggregation sp's for pretty large (200 million) and extremely volatile (rolling 10 days) dataset of airline quotes. This would let us replace a bunch of horrible legacy code and a ton of tables that all model the same data at different levels of aggregation.

My company is moving to a Test driven development approach which I really like. TTD makes complete sense to me for c# or python work. I'd love to have something similar for the database without having to have an abstraction layer on top (a test framework using on TSQL). This would have to be done to support continuous deployment which we also want to move to. At the moment the database development work slows everything down into static release cycles.

My first thoughts were to have a tests schema and to put stored procs analogous to c# unit tests inside there that start a transaction and a try catch block then run whatever object you want to test. Then make some assertions and do *something*. Return a error value. Whatever that could be monitored by a test runner.

I've had a look round the interweb' and have found a bunch of frameworks. They seem to be expansions of that idea.

The main problems I can see are:

1) Mocking - how do you mock out tables without breaking things.
2) Transactional control -- is there a problem when a proc does a rollback?
3) INSERT EXEC problems. If a sp performs an INSERT EXEC then a) it's probably doing something wrong b) It's almost impossible to test.
...
...
More I haven't thought of.


What do you guys do?

Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION

denis_the_thief
Aged Yak Warrior

596 Posts

Posted - 2011-06-01 : 08:47:02
TTD sounds interesting - I don't have any answers - but do have questions?

1. Can't the same thing be accomplished with test robots/automated test scripts?

2. If an application was developed without TTD in mind, is it possible to add it later? Difficult to do that?

3. If the requirements change, won't the TTD code have to be rewritten anyways?
Go to Top of Page

Lumbago
Norsk Yak Master

3271 Posts

Posted - 2011-06-01 : 09:21:03
Did you read this article? ->

http://msdn.microsoft.com/en-us/magazine/cc164243.aspx

Even though I have no experience whatsoever regarding your questions I've always wanted to know how test driven development works and how it applies/can apply to database development. If you are able to find answers to your questions I'd really appreciate you posting them here so we all could learn a thing or two :)

- Lumbago
My blog-> http://thefirstsql.com/2011/02/07/regular-expressions-advanced-string-matching-and-new-split-function-sql-server-2008-r2/
Go to Top of Page

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2011-06-01 : 19:56:59
Hi Lumbago, denis

first typo -- TTD should be TDD (test driven development).

Lumbago - nice article, reading now

In short -- before you write *any* production code you write a (failing) test that describes the desired behaviour. Then write the simplest code that will satisfy the test. Rince and repeat and soon you have a test set that should provide regression when you start to change something else.

For C# or python for example:

In general to unit test a specific object you would 'Mock' out other object that the test target depends on. For instance you could mock out a database layer so that the object you are testing gets a static dataset back from what it thinks is a database call. Inversion of control is really useful there using some sort of IOC container like castle.

When I'm working with another developer in python or c# on data layers we'll use test driven development and pair programming quite heavily. Generally we "ping pong" it -- one of us writes the unit test and then gives the keyboard to the other developer to write the functionality. Then reverse rolls. Pair programming is really tough - you have to be constantly talking about what you are doing when you are coding and thinking about the other developers code when they are coding. it's tiring but it results in really nice code. Our company has been doing this for a while and it was hell to start with but we are starting to see the benefits in our front end code.

The end goal is to move to a continual deployment setup where we can push code with confidence (the tests)

Dennis:
quote:
1. Can't the same thing be accomplished with test robots/automated test scripts?

possibly -- don't think there is much of conceptual difference between a test script and a unit test (a unit test could be considered a script). One of the end goals is to automate the testing to support continual deployment.

quote:
If an application was developed without TTD in mind, is it possible to add it later? Difficult to do that?

Yup -- it's like pulling teeth. Looking through the code base I've found a ton of stored procs that have "test" calls in comments. When you try and run them the comment no longer matches the sp and the sp doesn't work. A proper unit test framework should be run whenever a checkin / change is made. We aren't even going to try and rewrite tests for all the legacy code but as we develop new stuff we should write tests for them if possible.

quote:
3. If the requirements change, won't the TTD code have to be rewritten anyways?

This is actually what I see as the biggest *advantage* of them. They let you know that some assumption or requirement is no longer being fulfilled when you change something. If tests start failing then you know that something has changed in a way that no longer works for your business rules.


It's a lot easier to mock out objects in python or c# than it is in the database because the logic in there is so intrinsically connected to *data*

I'd love to hear from any of you that do continual deployment how you manage changes to the database schema / objects...

I'll try and keep this thread updated with details of what we try and implement. this is one of the areas of database development that I think doesn't get considered very often.

Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
Go to Top of Page

denis_the_thief
Aged Yak Warrior

596 Posts

Posted - 2011-06-02 : 15:28:23
quote:
Originally posted by Transact Charlie

Hi Lumbago, denis
...
don't think there is much of conceptual difference between a test script and a unit test (a unit test could be considered a script). One of the end goals is to automate the testing to support continual deployment.

...

Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION




That is what I am scratching my head over. Some promote TDD like it is a new thing and maybe it is but, I used to use a test robot application way back, you record your interaction with the appliation. Then the Robot will re-play it for regression test and compare outcomes.

I read some of the article. I found it interesting how it did a begin tran/ roll back so as to not alter the test environment. Another way do do that, and not neccessarily better, is to save your Database when starting. Then you need to restore before you run your test scripts.
Go to Top of Page

robvolk
Most Valuable Yak

15732 Posts

Posted - 2011-06-02 : 16:18:47
Mladen (spirit1) has some relevant material on his blog:

http://weblogs.sqlteam.com/mladenp/archive/2010/11/23/the-red-gate-guide-to-sql-server-team-based-development.aspx
http://weblogs.sqlteam.com/mladenp/archive/2010/06/04/SQL-University-Database-testing-and-refactoring-tools-and-examples.aspx
Go to Top of Page

mbaylon
Starting Member

2 Posts

Posted - 2011-06-03 : 10:10:36
I've written a few blogs on tdd/unit testing sprocs that might be of interest

http://dbtestunit.wordpress.com/category/stored-procedure/
Go to Top of Page

Transact Charlie
Master Smack Fu Yak Hacker

3451 Posts

Posted - 2011-06-14 : 07:19:45
Just a quick update - we're still talking about how we are going to do this but many people are on holiday so there's no consensus:

Points that came up

1) There seems to be no way we could do 'in database' testing of objects that return more than one result set. We have a lot of sp's that return multiple result sets and there's no way yo get the information out of them in the database layer using INSERT EXEC or OPENROWSET -- or does anyone know a funky way?

So we're leaning towards an NUNIT wrapping framework to write our unit tests in that will be committed along with the database code (somehow).

Can I ask again -- if any of you have experience with continual deployment then I'd love to hear about your processes and experiences.

Or is this just not a *thing* in the database community?

Charlie.

Charlie
===============================================================
Msg 3903, Level 16, State 1, Line 1736
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION
Go to Top of Page

mbaylon
Starting Member

2 Posts

Posted - 2011-06-14 : 18:42:48
Charlie, if I have understood what you are asking then - my take on including database development in an overall continuous integration process:

1. All devs have own database sandbox environment
2. Always start with a baseline database schema - based on current production db schema ie the target deployment. All changes are placed in 'atomic' individual SQL scripts
3. Source control used eg subversion. With tags/labels easy to get scripts/changes deployed in a specific database version
4. All change scripts (for whole project team) placed in dir 'WorkingDirectory' - which is under source control
5. Prefix added to name of script files to ensure running order eg 001_CreateTable, 002_CreateSproc etc
6. Test first approach taken. Write tests - then write SQL script that passes test.
7. Tests written in C#. I've use a framework I've created - see http://dbtestunit.wordpress.com - there are a number of others that could be used.
8. All code/scripts/tests under source control
9. Use automated build tools - such as cruise control/nant.
10. Auto build when a developer checks in code (at a minimum this should be done once a day - a 'nightly build'). All done in a separate 'build' environment.
11. All code - including database scripts are automatically built from source code and all unit tests run.
12. Build tools autogens version number for whole system eg 2.0.1.278
12. Database schema can be versioned eg includes a 'dbo.BuildVersion' table
13. Build process (eg using nant token replacement) can version the overall db schema using 'dbo.BuildVersion' table and individual script files eg using extended properties
14. If all unit tests pass - changes then can be automatically passed to other environments eg deployment, integration and performance testing.
Go to Top of Page
   

- Advertisement -