|
|||||||
New to SitePoint Forums? Register here for free!
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
How extensively should one test?
I am trying to learn using Simpletest, so I wrote tests for the DB connection class and wrote the class itself. Here's how it looks like (test names should be self-explanatory):
PHP Code:
PHP Code:
In my example there's quite a lot of code in the tests... Do you think all the tests are proper or are some of them unneccessary at all? Now since I pretty much finished it, any comments on this would be greatly appreciated. |
|
|
|
|
|
#2 |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Test until you are confident. I would say that you haven't over tested, but you have over asserted . When a test fails, you want to quickly go to the point of failure to see what went wrong. The ...assert(is_object()) call just add clutter I think, also the repeated checking for no error. You can always debug this stuff once you get the failure.One way to think about this is to just say in words what you want done. That becomes the test title of course, and the expected result is yourassertion. That way you usually only write one or two assertions each time. Minor quibble. I would test for pattern sin the error messages, rather than exact lettering. The tests should be an aid to refactoring, but if you have to edit them every time you change the wording of a message they will really start to irritate. I would expect fairly excessive testing of a connection object. Lot's of things can go wrong. On average I get about as much test code as real code. yours, Marcus |
|
|
|
|
|
#3 | ||
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
Quote:
Quote:
|
||
|
|
|
|
|
#4 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Quote:
PHP Code:
Anyway, you'll find on the first refactor those tests that help and those that hinder. BTW one thing I have found useful about the connection type objects is to add transaction support too and fold the close method into the disconnection. It becomes a MysqlTransaction object then, which I personally find easier to work with. You just go... PHP Code:
yours, Marcus |
|
|
|
|
|
|
#5 |
|
simple tester
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Sep 2003
Location: Glasgow
Posts: 1,685
|
I think I might disagree with Marcus about too many error assertions. You've got query methods which can be called repeatedly during the lifetime of the object. Each call must reset the error state depending on whether the query failed or not. If you were using mysql_error() rather than setting your own error strings (I'd probably prefer the former since they're more informative) you'd automatically get the error relating to the last query. Thus you could test once to make sure that mysql_error is in fact wired up to the getError method and then forget all about it in the other tests.
However, since you're setting your own error values, you can't rely on mysql_error automatically resetting itself with each new query. It would be possible to write an implementation which persisted error states between queries and therefore that should be one of the constraints. Checking the getError value in each test might not be such a bad idea but if you can think of a single test to deal with remembered errors that would be better. Better still if you can avoid setting error properties in the first place - there's no state to be remembered. There's a cheat I use a lot for errors: PHP Code:
Do you really need the error() method? In the calling script, you could just check if the getError return value is an empty string. I'd be tempted to take the database selection out of there in order to simplify things. Finallty, I think you're definitely on the right track overall. Unit tests should be fine-grained. If something fails, you want the tests to tell you what and why. Test every last detail which is of interest. Ignore everything which isn't so you don't over-constrain possible solutions. In saying that, I wrote a 130-line class tonight with a 400-line unit test so I seem to be well off the 1:1 test/code ratio. |
|
|
|
|
|
#6 | ||
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
Thanks, comments of both of you are really helpfull.
Marcus: PHP Code:
I do see a lot of error assertions in my tests, but I can't see a way to reduce the count, however, I'd really like to have it reduced. McGruff: Quote:
PHP Code:
PHP Code:
Quote:
|
||
|
|
|
|
|
#7 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Quote:
If you get any kind of error, don't return the result. Then test for the result only when looking at a happy path. yours, Marcus |
|
|
|
|
|
|
#8 | ||
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
Quote:
Quote:
Here's how I look at it. When writing tests, you define certain behaviour you want the class to have. Let's take the same valid manipulate() call. Before writing the test, I formulate the behaviour as this: when running a valid query with manipulate(), it should do what's in the SQL sentence AND, since it has done it correctly, it should return no error ($db->error() === false). The first part of the requirement (before 'AND') your test fullfills - you run valid query and check (via query()) if it actually performed the SQL instruction. But the test simply doesn't cover an important thing - there should be no error after running the query. When writing the test, I imagine how I will be using the class: I would run manipulate() and immediately after that I would check if any error occured. If the query was valid, no error should be there. But the test simply does not cover the error part. Thus 'I do not know' if after running valid manipulate() query, I would not get any error, hence I would write the no-error assertion. This example you gave me below was in response to my comment 'I should run a valid query successfully, and I should get no errors after that', but I think it's a bit incorrect since although it shows two tests for query() and manipulate(), error check is present in one only and not another. PHP Code:
![]() |
||
|
|
|
|
|
#9 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Firstly, let me say that this whole niche is pretty new. I could be way off and you may be utterly correct. However... ![]() Quote:
Also, do you really trust that write just because no error was reported? That is placing a lot of trust in the code. As you have to make the stronger (read back) test anyway, why not do just that one. This is at teh test level of course. You may, at the code level, want to return false if the row was not written. For example, a duplicate key. Again, I would have a separate test for this for this case. I suspect though, that you will never check the return value in the code either. You might be designing ahead with such a return value. Tests are also documentation for the system. Having clear tests is nice. yours, Marcus |
|
|
|
|
|
|
#10 | |
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
All right, so if I understand it correctly, you suggest separating main functionality tests from error reporting tests, right?
Quote:
|
|
|
|
|
|
|
#11 |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi.
Test until you are confident. Remember, unit tests are white box tests. This means you can use the code to guide you as to what will break. yours, Marcus |
|
|
|
|
|
#12 |
|
SitePoint Addict
![]() ![]() ![]() Join Date: Aug 2005
Location: Lithuania, Europe
Posts: 295
|
Yeah, I do want to test untill I am confident, just want to not have any redundant tests and avoid some possible mistakes... Was expecting a bit more 'yes/no' answer to my last post.
![]() |
|
|
|
|
|
#13 |
|
SitePoint Guru
![]() ![]() ![]() ![]() ![]() Join Date: Apr 2004
Location: Quincy
Posts: 645
|
How extensively should one test?
Every possible thing. Every conceivable thing. Remember, for every section of untested code, you will likely have as many bugs as you do users. ![]() |
|
|
|
![]() |
| Bookmarks |
«
Previous Thread
|
Next Thread
»
| Thread Tools | |
| Display Modes | |
|
|
|
All times are GMT -7. The time now is 13:44.






. When a test fails, you want to quickly go to the point of failure to see what went wrong. The ...assert(is_object()) call just add clutter I think, also the repeated checking for no error. You can always debug this stuff once you get the failure.



Linear Mode
