.NET Forum / Languages / C# / April 2008
Creating a unit test in vs2008 for an object that holds strings?
|
|
Thread rating:  |
Andy B - 07 Apr 2008 17:51 GMT I have a class called Address. It holds strings to represent different parts of an address (street, city, state, zipCode). It doesn't really have anything in it other than a blank constructer and some default properties to set and get the string values. How would you write tests on this class to make sure everything is running ok? Or are tests on something like a string container like this not really useful? Let me know what some ideas are. The thing that would be tested for is that there are only strings being saved in the container and nothing else. I thought of even putting a constructer to create the address itself instead of having to assign every property.
Andy - 07 Apr 2008 20:42 GMT > I have a class called Address. It holds strings to represent different parts > of an address (street, city, state, zipCode). It doesn't really have [quoted text clipped - 5 lines] > the container and nothing else. I thought of even putting a constructer to > create the address itself instead of having to assign every property. If all it does is store whatever values its given, I'd say that it's not worth writing something to test it. Save your time to code tests for complex things, actual business rules, etc.
Andy B - 07 Apr 2008 21:24 GMT That's kind of what I figured, but thought I would put it out here in case I was wrong somehow.
>> I have a class called Address. It holds strings to represent different >> parts [quoted text clipped - 15 lines] > not worth writing something to test it. Save your time to code tests > for complex things, actual business rules, etc. Ben Voigt [C++ MVP] - 07 Apr 2008 21:43 GMT > That's kind of what I figured, but thought I would put it out here in > case I was wrong somehow. As long as this type is used in the public methods of other types you do have unit tests for, it will be tested as a side effect of those other tests.
>>> I have a class called Address. It holds strings to represent >>> different parts [quoted text clipped - 16 lines] >> not worth writing something to test it. Save your time to code tests >> for complex things, actual business rules, etc. Andy B - 07 Apr 2008 21:45 GMT What do you mean? So, your saying that if I used the Address type as a parameter to another method that gets tested, then the address gets tested anyways?
Guess there's not much logic to an address eh? sounds kind of funny...
>> That's kind of what I figured, but thought I would put it out here in >> case I was wrong somehow. [quoted text clipped - 23 lines] >>> not worth writing something to test it. Save your time to code tests >>> for complex things, actual business rules, etc. Ben Voigt [C++ MVP] - 08 Apr 2008 14:55 GMT > What do you mean? So, your saying that if I used the Address type as a > parameter to another method that gets tested, then the address gets > tested anyways? Yes. If the only "behavior" of the Address class is to carry data to/from other classes, then that's all you need to test, and the unit tests of the other class do that.
> Guess there's not much logic to an address eh? sounds kind of funny... >>> That's kind of what I figured, but thought I would put it out here [quoted text clipped - 3 lines] >> you do have unit tests for, it will be tested as a side effect of >> those other tests. Alun Harford - 07 Apr 2008 22:10 GMT > I have a class called Address. It holds strings to represent different parts > of an address (street, city, state, zipCode). It doesn't really have [quoted text clipped - 5 lines] > the container and nothing else. I thought of even putting a constructer to > create the address itself instead of having to assign every property. It depends.
The biggest reason for writing tests is to allow somebody else (or you) to refactor your code and easily tell if they have broken it.
Another reason is that it clearly documents how the class should be used.
Lets say you decide to validate Zip Codes against States... If you have unit tests, you can easily tell if you have broken the basic behavior. If you don't have tests, you might introduce bugs in the process.
However, tests are not always a good thing. In this case, they could get brittle and slow the development process (since, for example, you might refactor Address away entirely, pull it in from a database, etc).
Unit tests cost time. Bugs cost time. Write the unit tests if they cost less than the bugs. Let the bugs happen if they cost less than the unit tests (eg. If you're writing a *truely* throwaway app).
If in doubt, I'd write tests.
And if you're writing so many of these types of classes that you need to care about whether they need tests, you probably need to rethink your architecture.
Alun Harford
</long, winding post>
Andy B - 07 Apr 2008 22:48 GMT What is a throw away app? and I didn't know how to make a serializable object, so I made an xsd file and ran it through xsd not knowing what it would come up with...guess that can kind of get you in trouble ...
>> I have a class called Address. It holds strings to represent different >> parts of an address (street, city, state, zipCode). It doesn't really [quoted text clipped - 35 lines] > > </long, winding post> Alain Boss - 08 Apr 2008 15:55 GMT Andy B schrieb:
> I have a class called Address. It holds strings to represent different parts > of an address (street, city, state, zipCode). It doesn't really have [quoted text clipped - 5 lines] > the container and nothing else. I thought of even putting a constructer to > create the address itself instead of having to assign every property. If you only use some getters/setters on this class i wouldn't spend much time on unit tests. however, the described class could be improved considerably.
i would implement it as an immutable type with only getters and a constructor. this would reduce the problem you have when you change the zip-code but not the city and the state. remember, even when you change them one after the other the state of your instance is incorrect during the modifications. furthermore your type will not be thread-safe.
you will need some rules to verify that zip-code and city actually match and to ensure that the zip code is in the correct format. so, you eventually will implement business-rules on this type ...
now, if you add the rules to your setters you'd get some silly exceptions if the zip doesn't match the city (when changing the zip after the city) or vice versa.
so, make the type immutable, create business-rules and verify them and finally test them.
Alain
Ben Voigt [C++ MVP] - 08 Apr 2008 16:29 GMT > you will need some rules to verify that zip-code and city actually > match and to ensure that the zip code is in the correct format. so, [quoted text clipped - 6 lines] > so, make the type immutable, create business-rules and verify them and > finally test them. You're in for a world of hurt if you try to write rules to validate postal codes. (pun intended)
> Alain Alain Boss - 08 Apr 2008 17:09 GMT > You're in for a world of hurt if you try to write rules to validate postal > codes. (pun intended) well, there is a world outside US ;-)
Ben Voigt [C++ MVP] - 08 Apr 2008 23:39 GMT >> You're in for a world of hurt if you try to write rules to validate >> postal codes. (pun intended) > > well, there is a world outside US ;-) That's exactly my point. It's effectively impossible to write rules to accept any valid address (except the trivial one, which permits anything at all, and is what you recommended that the OP change).
Alain Boss - 09 Apr 2008 09:49 GMT Ben Voigt [C++ MVP] schrieb:
>>> You're in for a world of hurt if you try to write rules to validate >>> postal codes. (pun intended) [quoted text clipped - 3 lines] > accept any valid address (except the trivial one, which permits anything at > all, and is what you recommended that the OP change). my main recommendation was to make the type immutable and i stick to that. you could for instance add a rule that zip code only contain characters a-Z and 0-9 or only numbers or whatever. the same is true for cities where numbers and special characters are not allowed. these are simple rules and i'd recommend to implement and test them.
if the type is not immutable it is actually possible to get wrong addresses.
Andy B - 09 Apr 2008 12:51 GMT > my main recommendation was to make the type immutable and i stick to > that. you could for instance add a rule that zip code only contain > characters a-Z and 0-9 or only numbers or whatever. the same is true for > cities where numbers and special characters are not allowed. these are > simple rules and i'd recommend to implement and test them. That wasn't the original issue. Business rules are in a different section of the code than the object itself. Testing if addresses were actually valid wasn't the thing. What was needed, was a yes or no type of answer on whether or not a string container like an address type should be tested to see if there was any problems with its ability to hold and retain the raw strings that it was given.
> if the type is not immutable it is actually possible to get wrong > addresses. How is this possible? If you do something like:
Address Address = new Address(); Address.City = "A city";
I guess I just don't get how you can say that if "a city" is given to address.city, how that could eventually be the wrong city name?
Alain Boss - 10 Apr 2008 08:58 GMT Andy B schrieb:
> How is this possible? If you do something like: > > Address Address = new Address(); > Address.City = "A city"; you have to threads A and B and both access the same address. thread A changes the address from address.City = "Zurich"; adress.ZipCode = "8000"; to address.City = "Berne"; adress.ZipCode = "3000";
When thread B accesses the instance between the change of zipCode and City it would get address.City = "Berne"; adress.ZipCode = "8000";
although the object looks ok and no rules prohibit this, the address is actually wrong. with an immutable type thread B would get an old, but correct address, until the new address is available completely.
Andy B - 08 Apr 2008 16:47 GMT Um... what does this mean? It is part of a larger class that will get written to an xml file. The last I knew of, XmlSerializer.Serialize required that the properties to be written be read/write. Any readonly properties got ignored? Am I wrong with this? immutable? this is the first time I heard of such a thing in programming. What is it and how do you use it?
> Andy B schrieb: >> I have a class called Address. It holds strings to represent different [quoted text clipped - 30 lines] > > Alain Alain Boss - 08 Apr 2008 23:35 GMT > Um... what does this mean? It is part of a larger class that will get > written to an xml file. The last I knew of, XmlSerializer.Serialize required > that the properties to be written be read/write. Any readonly properties got > ignored? Am I wrong with this? > immutable? this is the first time I heard of such a thing in programming. > What is it and how do you use it? try this for a start http://winfxworld.spaces.live.com/Blog/cns!763BFEA85DD32432!177.entry
regards alain
Arne Vajhøj - 16 Apr 2008 03:19 GMT > If you only use some getters/setters on this class i wouldn't spend much > time on unit tests. Believe it or not, but I have actually seen getters and setters being wrong after too much copy paste (it was not C# but that does not really matter).
As a consequence I am paranoid enough to even make unit tests for that type of class.
Arne
Alain Boss - 16 Apr 2008 06:53 GMT >> If you only use some getters/setters on this class i wouldn't spend >> much time on unit tests. [quoted text clipped - 7 lines] > > Arne Well, i have seen setters in legacy code that are longer than my arm too. In this case Unit tests are definitely called for.
alain
Ben Voigt [C++ MVP] - 17 Apr 2008 14:28 GMT >> If you only use some getters/setters on this class i wouldn't spend >> much time on unit tests. > > Believe it or not, but I have actually seen getters and setters > being wrong after too much copy paste (it was not C# but that does > not really matter). These bugs should be found by the unit tests for the consumer classes.
> As a consequence I am paranoid enough to even make unit tests > for that type of class. > > Arne Arne Vajhøj - 20 Apr 2008 03:51 GMT >>> If you only use some getters/setters on this class i wouldn't spend >>> much time on unit tests. [quoted text clipped - 3 lines] > > These bugs should be found by the unit tests for the consumer classes. Usually will.
And if the consumer class is done by the same team at the same time, then no big deal.
But another team taking a drop finding the bug 3 months later will not be pleased.
Arne
Lasse Vågsæther Karlsen - 09 Apr 2008 17:30 GMT > I have a class called Address. It holds strings to represent different parts > of an address (street, city, state, zipCode). It doesn't really have [quoted text clipped - 5 lines] > the container and nothing else. I thought of even putting a constructer to > create the address itself instead of having to assign every property. To be honest I'm a bit ambivalent to this question.
On one hand I advocate testing everything, for various reasons (I'm getting to those), but on the other hand, a class that holds strings (struct with fields?), do you really foresee much problems in creating that class?
My goal for 100% tests is to be able to do code coverage that ends up in 100% coverage. If you can attain that, it's easy to figure out what parts of your code you're missing a test for, you can just run code coverage.
On the other hand, I also advocate writing the tests first, so that you can afterwards check that the class functions according to specifications.
But, if you don't want to, or can't, go to 100% code coverage for unit tests, you should prioritize your tests, so that you don't spend time writing tests for one class that really should've been spent on writing tests for another more important class.
Basically, for each class/code blocks/testable unit, you should decide on the following two criteria:
1. what is the risk of this code being wrong? 2. what is the consequence of this code being wrong?
If the answer to the above questions are:
1. low 2. little
then write the test to it last.
If on the other hand the answers are:
1. medium to high (complex class) 2. critical showstopping bug (payment system down, ordering system producing the wrong orders, etc.)
then by all means, test it to death.
To me, it sounds like your class belongs in the first category. Not much that can go wrong. It might have dire consequences if it goes wrong, but you also need to decide on what could go wrong. If one thing that could go wrong was that a field of the class was null, and this could crash your app with a null reference exception, then it would depend on the application wether this was "critical" or not.
I don't think anyone but you yourself can really decide wether the class is worthy of its own test or not.
Personally I would write a test for it, but it would be written towards the end of the project, given enough time to do it, at least with what you've told us about it so far.
 Signature Lasse Vågsæther Karlsen mailto:lasse@vkarlsen.no http://presentationmode.blogspot.com/ PGP KeyID: 0xBCDEA2E3
Andy B - 09 Apr 2008 19:44 GMT I can't reveal all of the details of the Contract object for security reasons, but it does make use of 18 other objects and data types that have been created for the Contract object's sole use. So, The Contract object "owns" 18 other objects/data types. And of course, the Contract object itself + the other 18 objects/data types it owns has other fields and properties of different data types. It seems to be quite complex, but the main purpose of the Contract object is to hold and store validated data that makes up the actual Contract document and all of its parts. The Contract object also holds different states of the Contract itself (Signed, Fulfilled and so on). Would this Contract class need to have it's test written before the creation of it? or do you think it can wait until the code for the object has been written first.
>> I have a class called Address. It holds strings to represent different >> parts of an address (street, city, state, zipCode). It doesn't really [quoted text clipped - 60 lines] > the end of the project, given enough time to do it, at least with what > you've told us about it so far.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|