Page 1 of 1
Help with TDD
Posted: Thu Mar 06, 2008 8:33 am
by allspiritseve
Hello all,
I have just started trying to change my development process to testing first. I am having a bit of trouble though-- I can see how it works with methods that take inputs, and give certain outputs based on that input-- I don't understand how to write tests for methods that maybe return true or false, like method that updates or inputs into a database. How do I test those methods? I keep getting stuck trying to write more tests, and get frustrated with the whole process. Can anyone recommend some good tutorials that might help?
Thanks,
Cory
Re: Help with TDD
Posted: Thu Mar 06, 2008 12:58 pm
by Christopher
allspiritseve wrote:I don't understand how to write tests for methods that maybe return true or false, like method that updates or inputs into a database. How do I test those methods?
Which tutorials have you looked at? Which test framework are you using?
For the methods you mention, you should check both the return value and that the updated value in the database is what is expected. You may want to Mock the database object so you can check the interaction directly.
Re: Help with TDD
Posted: Thu Mar 06, 2008 3:24 pm
by allspiritseve
Just basic tutorials such as the logger for SimpleTest (which is the test framework I use).
Re: Help with TDD
Posted: Fri Mar 07, 2008 8:14 am
by McGruff
All classes which know how to persist themselves would follow the same sort of outline: create the object, save it, load a new instance, and check the object's state was remembered.
Code: Select all
class MyTestCase extends UnitTestCase {
function setUp() {
...
...
}
function testSaveAndLoad() {
$foo = new Foo(...);
$foo->setBar('some value');
$foo->save();
$foo_2 = new Foo(...);
$this->assertEqual($foo_2->getBar(), 'some value');
}
}
Don't mock the database connection object. You'd have to make assertions about sql arguments passed to the mock but this isn't practical. Use a real database set up and torn down for the tests.
More here.
Re: Help with TDD
Posted: Mon Mar 10, 2008 12:09 pm
by Maugrim_The_Reaper
http://devzone.zend.com/article/3082-De ... evelopment
BDD article but it illustrates a process you can easily adapt to PHPUnit/SimpleTest with some translation and less pretty code. BDD is often described as part "doing TDD well" before anything else BDD offers becomes useful.
Re: Help with TDD
Posted: Thu Oct 23, 2008 1:09 pm
by josh
If you're testing the data gets persisted, you might inject a mock persistence object and assert that the mock object is being called properly, or assert that the correct SQL was generated by your persistence layer. Also on an unrelated note I think calling yourself "small" on your website is shooting yourself in the foot business wise.
Re: Help with TDD
Posted: Sun Oct 26, 2008 3:34 pm
by allspiritseve
jshpro2 wrote:If you're testing the data gets persisted, you might inject a mock persistence object and assert that the mock object is being called properly, or assert that the correct SQL was generated by your persistence layer.
As others have pointed out, its better not to mock the db... trying to match SQL queries results in very brittle tests, in which a space in the wrong spot could give you a false error. As I've discovered since I started this thread, not mocking the db is the way to go.
jshpro2 wrote:Also on an unrelated note I think calling yourself "small" on your website is shooting yourself in the foot business wise.
I do need to update that site... but depending on who you talk to, being a small business isn't such a bad thing.
Re: Help with TDD
Posted: Sun Oct 26, 2008 9:54 pm
by josh
Yeah matching generated SQL was bad advice, why is mocking your data mapper bad though? It allows you to mock the persistence layer when you test a model, and mock a model when you test your persistence layer ( right? )
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:12 pm
by allspiritseve
jshpro2 wrote:why is mocking your data mapper bad though?
Ah, I thought you meant mocking the db. I must have misunderstood you. Mocking data mappers is fine.
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:33 pm
by josh
Oh, haha yeah that would be worse than testing the SQL.
On another note should I be testing my controllers? Im finding tons of examples I can apply to writing tests for my models, but not much detailed instruction on testing my views, view helpers themselves, etc..
I'm also torn between Fowler not recommending BDD and Dan North advocating it, perhaps I don't have my brain wrapped around the concept as much as I'd like to think I do. If I have an object that's not hard to set up at all and is actually very basic, for example if I had a product object that is supposed to use a tax object to calculate its prices, that tax objects is all but the very simplest implementation of a strategy pattern. Is there really any reason not to mock that strategy pattern as simple as it is? I'm totally feeling the idea of testing the behavior and not the state, to not lock you into an internal implementation.
If you wrote a test in the product unit test to setPrice(100), then asserted that getPriceWithTax()==106, you might as well not even have a tax object. This is where Fowler just comes along and confuses the crap out of me.
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:39 pm
by josh
McGruff wrote:All classes which know how to persist themselves would follow the same sort of outline: create the object, save it, load a new instance, and check the object's state was remembered.
Isn't that coupling the persistence code to the business logic, both in the production code and in the tests? Which would be fine if you were using active record, correct? Correct me if I'm wrong which I'm sure you will
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:40 pm
by allspiritseve
jshpro2 wrote:On another note should I be testing my controllers? Im finding tons of examples I can apply to writing tests for my models, but not much detailed instruction on testing my views, view helpers themselves, etc..
Sure, the majority of what you're doing will probably be mocking your models and views and making sure the controller is dispatching to them properly. This is also a great opportunity to take advantage of get/post/session wrappers in order to mock the request.
Might want to check out this thread, particularly lastcraft's comment (creator of SimpleTest):
http://www.sitepoint.com/forums/showpos ... ostcount=5
jshpro2 wrote:I'm also torn between Fowler not recommending BDD and Dan North advocating it, perhaps I don't have my brain wrapped around the concept as much as I'd like to think I do. If I have an object that's not hard to set up at all and is actually very basic, for example if I had a product object that is supposed to use a tax object to calculate its prices, that tax objects is all but the very simplest implementation of a strategy pattern. Is there really any reason not to mock that strategy pattern as simple as it is? I'm totally feeling the idea of testing the behavior and not the state, to not lock you into an internal implementation. But then Fowler just comes along and confuses the crap out of me.
I've read a couple of articles on BDD, but I just don't buy the hype yet. TDD is still so new, and its working out pretty well for me so far...
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:43 pm
by allspiritseve
jshpro2 wrote:Isn't that coupling the persistence code to the business logic
Well, as he said, "all objects that know how to persist themselves", which basically means it is an ActiveRecord. The concept can be applied to gateways and mappers though... create an object, save it using the gateway/mapper, and then use the gateway/mapper to fetch it from the db and compare the two objects to make sure they are the same (I typically pick a property to compare).
Re: Help with TDD
Posted: Sun Oct 26, 2008 10:46 pm
by josh
Well take my product tax calculation example for instance, the product should behave in the same way whether it was using a flat rate calculation strategy or a strategy that represented a non taxable item, yes? If you simply test your inputs and outputs your couple you objects, which is the whole point of TDD, TDD is not just to test your code, you can test without doing TDD, TDD is supposed to help you write a non coupled design, by testing each
unit separately, but then Fowler just comes along and lists tons of reasons for not testing behavior and then admits he never tried it. I'm just confused is all
Edit: Hmm.. Just re read the part under "Test Isolation" (
http://www.martinfowler.com/articles/mo ... Stubs.html ) now I understand, basically I should avoid using mocks and use a real object where ever it would make sense to use a real object, correct?
Re: Help with TDD
Posted: Tue Nov 04, 2008 7:24 pm
by josh