53

I routinely run into this problem, and I'm not sure how to get past this hurdle. I really want to start learning and applying Test-Driven-Development (or BDD, or whatever) but it seems like every application I do where I want to apply is it pretty much only standard database CRUD stuff, and I'm not sure how to go about applying it. The objects pretty much don't do anything apart from being persisted to a database; there is no complex logic that needs to be tested. There is a gateway that I'll eventually need to test for a 3rd-party service, but I want to get the core of the app done first.

Whenever I try to write tests, I only end up testing basic stuff that I probably shouldn't be testing in the first place (e.g. getters/setters) but it doesn't look like the objects have anything else. I guess I could test persistence but this never seems right to me because you aren't supposed to actually hit a database, but if you mock it out then you really aren't testing anything because you control the data that's spit back; like I've seen a lot of examples where there is a mock repository that simulates a database by looping and creating a list of known values, and the test verifies that the "repository" can pull back a certain value... I'm not seeing the point of a test like this because of course the "repository" is going to return that value; it's hard-coded in the class! Well, I see it from a pure TDD standpoint (i.e. you need to have a test saying that your repository needs a GetCustomerByName method or whatever before you can write the method itself), but that seems like following dogma for no reason other than its "the way" - the test doesn't seem to be doing anything useful apart from justifying a method.

Am I thinking of this the wrong way?

For example take a run of the mill contact management application. We have contacts, and let's say that we can send messages to contacts. We therefore have two entities: Contact and Message, each with common properties (e.g. First Name, Last Name, Email for Contact, and Subject and Body and Date for Message). If neither of these objects have any real behavior or need to perform any logic, then how do you apply TDD when designing an app like this? The only purpose of the app is basically to pull a list of contacts and display them on a page, display a form to send a message, and the like. I'm not seeing any sort of useful tests here - I could think of some tests but they would pretty much be tests for the sake of saying "See, I have tests!" instead of actually testing some kind of logic (While Ruby on Rails makes good use of it, I don't really consider testing validation to be a "useful" test because it should be something the framework takes care of for you)

Wayne Molina
  • 19,158
  • 26
  • 98
  • 163
  • 15
    I just gotta say... I *love* the title of this question. – Shog9 May 09 '09 at 02:30
  • 2
    This is a very good question. I believe most of the time when we heard arguments on cost-justification of TDD, they are indeed talk specifically about CRUD-like application. – Sake May 09 '09 at 06:15
  • 4
    That's what I've noticed as well. I *want* to use TDD (well not necessarily TDD, but testing) but I can never think of what to test when the app just needs to pull data - I've gotten some great replies here, though. – Wayne Molina May 09 '09 at 11:48

9 Answers9

14

"The only purpose of the app is basically to pull a list of contacts"

Okay. Test that. What does "pull" mean? That sounds like "logic".

" display them on a page"

Okay. Test that. Right ones displayed? Everything there?

" display a form to send a message,"

Okay. Test that. Right fields? Validations of inputs all work?

" and the like."

Okay. Test that. Do the queries work? Find the right data? Display the right data? Validate the inputs? Produce the right error messages for the invalid inputs?

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • @S.Lott What your describing here is more behavior type testing at a unit level as opposed to TDD. I agree that each of the area's you have mentioned are prime candidates for unit tests. – David Yancey May 13 '09 at 23:44
  • If they define "pull" in testable form, then the tests drive the design of "pull". If they define "display them on a page" in terms of some testable result, then the tests drive the design of "display". It feels like TDD to me. – S.Lott May 14 '09 at 00:24
  • I agree to that as long as the tests drive the design and not test the behavior. – David Yancey May 15 '09 at 02:29
  • 1
    @DavidYancey Of course you're testing the behavior. This is what is being designed, how an object (and in aggregate, a system of objects) behaves. TDD is using tests for the desired behavior to drive the design by specifying the interfaces for said behavior. – Huperniketes Aug 05 '16 at 01:39
  • When talking about TDD, they say never write a line of code before writing its test. So how should I write the tests for CRUD application? Because the MVC framework just populates the model from view inputs. So how should I test this? – Amir Pashazadeh Dec 10 '17 at 11:18
6

I am working on a pure CRUD application right now But I see lots of benefits of Unit test cases (note- I didn't say TDD)

I write code first and then the test cases- but never too apart- soon enough though

And I test the CRUD operations - persistence to the database as well.

When I am done with the persistence - and move on to the UI layer- I will have fair amount of confidence that my service\persistence layer is good- and I can then concentrate on the UI alone at that moment.

So IMHO- there is always benefit of TDD\Unit testing (whatever you call it depending on how extreme you feel about it)- even for CRUD application You just need to find the right strategy for- your application

Just use common sense....and you will be fine.

RN.
  • 997
  • 4
  • 14
  • 31
5

I feel like we are confusing TDD with Unit Testing.

Unit Testing are specific tests which tests units of behaviors. These tests are often included in the integration build. S.Lott described some excellent candidates for just those types of tests.

TDD is for design. I find more often then not that my tests I write when using TDD will either be discarded or evolve into a Unit Test. Reason behind this is when I'm doing TDD I'm testing my design while I'm designing my application, class, method, domain, etc...

In response to your scenario I agree with what S.Lott implied is that what you are needing is a suite of Unit tests to test specific behaviors in your application.

David Yancey
  • 2,020
  • 1
  • 16
  • 21
4

TDDing a simple CRUD application is in my opinion kind of like practicing scales on a guitar- you may think that it's boring and tedious only to discover how much your playing improves. In development terms - you would be likely to write code that's less coupled - more testable. Additionally you're more likely to see things from the code consumer's perspective - you'll actually be using it. This can have a lot of interesting side effects like more intuitive API's, better segregation of concerns etc. Granted there are scaffold generators that can do basic CRUD for you and they do have a place especially for prototyping, however they are usually tied to a framework of sorts. Why not focus on the core domain first, deferring the Framework / UI / Database decisions until you have a better idea of the core functionality needed - TDD can help you do that as well. In your example: Do you want messages to be a queue or a hierarchical tree etc? Do you want them to be loaded in real time? What about sorting / searching? do you need to support JSON or just html? it's much easier to see these kinds of questions with BDD / TDD. If you're doing TDD you may be able to test your core logic without even using a framework (and waiting a minute for it to load / run)

Piotr Kaluza
  • 413
  • 2
  • 7
3

Skip it. All will be just fine. I'm sure you have a deadline to meet. (/sarcasm)

Next month, we can go back and optimize the queries based on user feedback. And break things that we didn't know we weren't supposed to break.

If you think the project will last 2 weeks and then never be reopened, automated testing probably is a waste of time. Otherwise, if you have a vested interest in "owning" this code for a few months, and its active, build some tests. Use your judgement as to where the most risk is. Worse, if you plan on being with the company for a few years, and have other teammates who take turns whacking on various pieces of a system, and it may be your turn again a year from now, build some tests.

Don't over do it, but do "stick a few pins in it", so that if things start to "move around", you have some alarms to call attention to things.

Most of my testing has been JUnit or batch "diff" type tests, and a rudimentaryy screen scraper type tool I wrote a few years ago (scripting some regex + wget/curl type stuff). I hear Selenium is supposed to be a good tool for web app UI testing, but have not tried it. Anybody have available tools for local GUI apps???

Roboprog
  • 3,054
  • 2
  • 28
  • 27
2

Just an idea...

Take the requirements for the CRUD, use tools like watij or watir or AutoIt to create test cases. Start creating the UI to pass the test cases. Once you have the UI up and passing maybe just one test, start writing the logic layer for that test, and then the db layer.

For most users, the UI is the system. Remember to write test cases for each new layer that you are building. So instead of starting from the db to app to ui layer, start in the reverse direction.

At the end of the day, you would probably have a accumulated a powerful set of regression test set, to give you some confidence in doing refactoring safely.

this is just an idea...

zeroin23
  • 1,821
  • 4
  • 20
  • 26
  • Interesting... I will look up these tools. Thank you. My personal choice is to develop application bottom- up instead. I come from enterprise application background- so have greater respect for the Service layer and Database model- so like to tackle that first. But what you say- makes sense as well – RN. May 11 '09 at 16:28
  • this might interest you too... http://fitnesse.org/ FitNesse enables customers, testers, and programmers to learn what their software should do, and to automatically compare that to what it actually does do. It compares customers' expectations to actual results. – zeroin23 May 13 '09 at 11:11
  • That's typically how BDD is done, you can think of it as two concentric circles, the outer one is the high level feature, the inner one is the lower level implementation that the high level depends upon. You start with the high level using tools like fitnesse or cucumber, then you define each of the steps as a high level executable test using capybara or selenium, from there you work out the middle layer and finally data layer. This approach gives you the functionality full vertical slices at a time. – Piotr Kaluza Jan 26 '13 at 07:56
1

These days you should not need much hand written code for a CRUD app apart from the UI, as there are a 101 frameworks that will generate the database and data access code.

So I would look at reducing the amount of hand written code, and automating the testing of the UI. Then I would use TDD of the odd bits of logic that need to be written by hand.

Ian Ringrose
  • 51,220
  • 55
  • 213
  • 317
1

I see what you are saying, but eventually your models will become sufficiently advanced that they will require (or be greatly augmented by) automated testing. If not, what you are essentially developing is a spreadsheet which somebody has already developed for you.

Since you mentioned Rails, I would say doing a standard create/read/update/delete test is a good idea for each property, especially because your test should note permissions (this is huge I think). This also ensures that your migrations work as you expected them to.

Oliver N.
  • 2,496
  • 19
  • 20
  • I'm not using Rails, but I used it as an example because it has "baked in" testing and that's what the tutorials normally say you should test. I see your point though. – Wayne Molina May 09 '09 at 02:23
1

I am working on a CRUD application now. What I am doing at this point is writing unit tests on my Repository objects and test that the CRUD features are working as they should. I have found that this has inherently unit tested the actual database code as well. We have found quite a few bugs in the database code this way. So I would suggest you push ahead and keep going with unit tests. I know applying TDD on CRUD apps is not as glamorous as things you might read about in blogs or magazines, but it is serving its purpose and you will be that much better when you work on a more complex application.

Mr. Will
  • 2,298
  • 3
  • 21
  • 27