I am not a Db guy. I am just curious if there is a possibility to write asserts in Sql so that you can write unit tests for your scripts, for your sprocs etc. and then even implement a Test Driven Development approach to your sessions?
thanks!
You can do that actually, not directly from SQL throught, but the language you do your application.
Of cause you SQL must be incapsulated in DAL (Data Access Layer) and all data got by Repositories (or other data access classes). You can do unit testing of those classes, that would be running SQL scripts at the end. So, basically you will test your SQL code.
It is simplier to me, than trying to write such tests in SQL. :)
Sometime ago I had thought on that:
http://www.beletsky.net/2010/11/testing-database-and-test-database.html
Related
I would like to test private procedures/functions in given pl/sql package (oracle environment).
I need rather simple test (run procedure, check DB if row exist/or check return value) but in complex testing suite.
Which tool / approach would you recommend me ? (It's not possible to use paid solution).
I'm using SQL developer so option #1 is it's internal JUnit testing framework.
Other option is utPLSQL, to be more independent of SQL developer.
Third approach is complete different.
I would use Apache JMeter to connect to DB a write tests in JMeter.
I'm quite familiar with this tool.
Downside is that it would be probably difficult/impossible for me to test private functions.
Your opinion ?
I don't get your "simple test in complex test suite". However if your main testing scenario is:
Set up test data in database table(s)
Run a PL/SQL subprogram
Verify the subprogram modified data in database table(s) correctly
I have a good news for you - http://dbfit.github.io/dbfit/ is a great tool for that kind of testing. I have used it in several occasions and I'm very happy with it.
Oh, and one can't access the package's private subprograms. You can only access package's public interface (the specification).
My team is developing a web application which should work on top of several RDBMS (Oracle and MSSQL). The developers have to write some database specific code for each database. Because of that the behavior on 2 different databases could be potentially different but should be identical. That why the QA guys have to perform all the test cases both against Oracle and MSSQL environment which is too costly for manual tests. Is there any way/tool/approach to perform manual tests against just one environment and to be sure that the behavior on the other environment is identical?
As you've discovered, manual testing makes it expensive to test the same software in multiple environments. The approach which allows you to solve this is to automate your tests. There are many tools for test automation, too many to list. Test automation has a myriad of benefits.
Otherwise if you must manual test, one technique you can do is have the database API connect to both databases. All queries go to both databases and the code checks the queries return the same results.
Since your queries are different, this might have to be done at a higher level of abstraction. For example, you'd have a subclass implementing Oracle and another implementing MSSQL. You'd create a wrapper object which, for every method, calls both the Oracle and MSSQL implementations and compares their results.
This will require that both databases are in the same state at the start of testing, particularly with the same sequences. It can run afoul of any sort of randomness or anything relying on time.
I want to implement Test First Development in a project that will be implemented only using stored procedures and function in SQL Server.
There is a way to simplify the implementation of unit tests for the stored procedures and functions? If not, what is the best strategic to create those unit tests?
It's certainly possible to do xUnit style SQL unit testing and TDD for database development - I've been doing it that way for the last 4 years. There are a number of popular T-SQL based test frameworks, such as tsqlunit. Red Gate also have a product in this area that I've briefly looked at.
Then of course you have the option to write your tests in another language, such as C#, and use NUnit to invoke them, but that's entering the realm of integration rather than unit tests and are better for validating the interaction between your back-end and your SQL public interface.
http://sourceforge.net/apps/trac/tsqlunit/
http://tsqlt.org/
Perhaps I can be so bold as to point you towards the manual for my own free (100% T-SQL) SQL Server unit testing framework - SS-Unit - as that provides some idea of how you can write unit tests, even if you don't intend on using it:-
http://www.chrisoldwood.com/sql.htm
http://www.chrisoldwood.com/sql/ss-unit/manual/SS-Unit.html
I also gave a presentation to the ACCU a few years ago on how to unit test T-SQL code, and the slides for that are also available with some examples of how you can write unit tests either before or after.
http://www.chrisoldwood.com/articles.htm
Here is a blog post based around my database TDD talk at the ACCU conference a couple of years ago that collates a few relevant posts (all mine, sadly) around this way of developing a database API.
http://chrisoldwood.blogspot.co.uk/2012/05/my-accu-conference-session-database.html
(That seems like a fairly gratuitous amount of navel gazing. It's not meant to be, it's just that I have a number of links to bits and pieces that I think are relevant. I'll happily delete the answer if it violates the SO rules)
It is doable. Create tests and in the setup create a new instance of db and give it some data and then execute the procs. Validate your assumptions, like I got the correct data back. Drop the test db then do it all again in the next test.
Unit testing in database is actually big topic,and there is a lot of different ways to do it.I The simplest way of doing it is to write you own test like this:
BEGIN TRY
<statement to test>
THROW 50000,'No error raised',16;
END TRY
BEGIN CATCH
if ERROR_MESSAGE() not like '%<constraint being violated>%'
THROW 50000,'<Description of Operation> Failed',16;
END CATCH
In this way you can implement different kind of data tests:
- CHECK constraint,foreign key constraint tests,uniqueness tests and so on...
How do you go about integration testing your database through your domain layer/model (repositories) that uses LINQ 2 SQL in the implementation and leave the DB as you found it? In other words, the ideal world of unit testing the DB, the integration test would leave the DB as it found it.
Are there tools out there that will handle this automagically? What are the best practices for performing integration tests on a DB through repositories?
The Spring Framework provides support for integration testing when using NUnit. The NUnit classes are located in the assembly Spring.Testing.NUnit.dll. In there are some classes that perform transaction management. These classes create and roll back a database transaction for each test. You simply write code that can assume the existence of a transaction.
Whether or not this will actually work with Linq to SQL is another matter. Spring says this works with ORMs. SQL Server 2008 allows you to nest transactions, so in theory you could start a transaction, perform your test through the Linq to SQL classes, and then
roll your transaction back. But I haven't
tried it.
Ryan Garaguay has an interesting article about this which uses TransactionScope and NUnit to roll back the database changes (although he is using SQLCommand and SQLConnection objects in his test code, rather than Linq)
I am trying to start a new MVC project with tests and I thought the best way to go would have 2 databases. 1 for testing against and 1 for when I run the app and use it (also test really as it's not production yet).
For the test database I was thinking of putting create table scripts and fill data scripts within the test setup method and then deleting all this in the tear down method.
I am going to be using Linq to SQL though and I don't think that will allow me to do this?
Will I have to just go the ADO route if I want to do it this way? Or should I just use a mock object and store data as an array or something?.
Any tips on best practices?
How did Jeff go about doing this for StackOveflow?
What I do is define an interface for a DataContext wrapper and use an implementation of the wrapper for the DataContext. This allows me to use an alternate, fake DataContext implementation in my tests (or mock it, if easier). This abstracts the database out of my unit tests completely. I found some starter code at http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx, although I've extended it so that it handles the validation implementations on my entity classes.
I should also mention that I have a separate staging server for QA, so there is live testing of the entire system. I just don't use an actual database in my unit testing.
I checked out the link from tvanfosson and RikMigrations and after playing about with them I prefer the mocking datacontext method best. I realised I don't need to create tables and drop them all the time.
After a little more research I found Stephen Walther's article http://stephenwalther.com/blog/archive/2008/08/17/asp-net-mvc-tip-33-unit-test-linq-to-sql.aspx which to me seems easier and more reliable.
So I am going with this implementation.
Thanks for the help.
You may want to find some other way around actually hitting the database for your unit tests because it takes a lot more time. That being said, have you considered using Migrations for creating / deleting your tables instead of using sql scripts? RikMigrations is what I have been using to create my database so I can easily revision all of my code in one place. Justin Etheredge has a great article on using RikMigrations.
Consider these methods on DataContext:
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.createdatabase.aspx
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executecommand(v=VS.100).aspx
I agree with much of the above, relating to unit testing. However, I think it's important to raise the point that using Mock Repositories and unit tests doesn't give you the same level of tests as a DB Integration Test would.
For example, our databases often have cascading deletes built right in to the schema. In this case, deleting a primary entity in an aggregate will automatically delete all child entities. However, this would not automatically apply in a mocked repository that was not backed up by a physical database with these business rules (unless you built all of those rules in to the Mock). This is important because if somebody comes along and changes the design of my schema, I need it to break my tests so I can adjust the code/schema accordingly. I appreciate that this is Integration Testing and not Unit Testing but thought it was worth mentioning.
My preferred option is to create a Master Design Database that contains sample data (the same sort of data you would create in your Mocks). During the start of each test run, I have an automated script that creates a backup of the MasterDB and restores it to "TestDB" (which all my tests use). That way, I maintain a repository of clean test data in Master than recreates itself upon each test run. My tests can play around with the data and test out all the scenarios needed.
When I debug the application, I have another script that backs up and restores the Master DB to a DEV database. I can play around with data here too without worrying about losing my sample data. I don't typically run this particular script every session because of the delay waiting for the DB to be recreated. I may run it once a day and then play around/debug the app throughout the day. If for example, I delete all the records from a table as part of my debugging, I would run the script to recreate the DevDB when I'm done.
These steps sound like they would add a huge amount of time to the process, but actually - they don't. Our application currently has in the region of 3500 tests, with about 3000 of them accessing the DB at some point. The database backup and restore typically takes around 10-12 seconds at the start of each test run. And since the whole test suite is only executed upon TFS checkin, we don't mind if we have to wait a while longer anyway. On an average day, our entire test suite takes about 15-20 minutes to run.
I appreciate and accept that integration testing is much slower than unit testing (because of the inherent need to use a real DB) but it more closely represents the 'real world' app. For example, Mock Repositories don't return DB error codes, the don't time-out, they don't lock up, they don't run out of disk space, etc.
Unit tests are ok for simple calculations, basic business rules, etc. and certainly they are absolutely the best choice for most operations that don't involve DB (or other resource) access. But I don't think they are as valuable as integration tests - people talk a lot about unit tests, but little is said about integration tests.
I expect those passionate about unit tests will be sending flames my way for this. That's fine - I'm just trying to bring some balance and to remind people that projects that are full of passed unit tests can still fail badly the moment you implement them in the field.
This article gives example of mocking linq to sql with typemock.
http://blog.benhall.me.uk/2007/11/how-to-unit-test-linq-to-sql-and.html