Should I test a class with no methods?
Let's say I have a configuration class that only has fields and I add a test that calls each field to see if they are there for example. But I think if one field is missing it would raise a compilation error in one of the calls or the field is not being used. So I think is rather pointless but I want some opinions.
Even though the class has no methods, in somecases it is very important to add test cases in your test program. For example,
If your class has constant types holding a specific value, then test cases are required to ensure those values are not modified.
In case if a class has some enum declrations with out specifying values, then test cases are required to ensure order of variables is intact.
If the type of declared variables needs to be strict (example: Many people stay on lighter side when it comes to double and float, but they cause very serious issues if altered especially in comparision operations), then test cases related to type check of variables should be added.
In case if a class has an array holding list of messages in a order (relaying on array index for a specific message), then test cases are required to ensure no message is induced in between.
Related
Let's say you have a class that has some arbitrary attributes:
class Data {
String a = '';
int b = 0;
bool c = false;
SomeObject d = SomeObject();
}
Let's also say somewhere you have a function that you want to reset most but not all of this Data object's attributes to those which do not correlate to the object constructor's default values.
Data data = Data();
...
void resetData() {
data = data
..a='reset'
..b=42
..c=true;
// We want to retain [d]'s state, for whatever reason.
}
How do you go about unit testing this behavior?
You could have a unit test that sets each attribute of Data to something entirely different from whatever the reset's default values are and verify that all of the relevant fields change, but that's 1) incredibly brittle and 2) defeats the purpose of what unit testing is for. If you added another object e that's supposed to be reset as well, but you forgot to add it to the resetData function, you almost certainly forgot to add it to the unit test as well. The unit test would then be providing no value, since the behavior would be broken but you would not be alerted to it.
Using reflection/introspection through dart:mirrors is an option by testing that each of that object's variables are indeed different (other than d), but dart:mirrors does not work with AngularDart so users of that are left high and dry.
I also couldn't find any libraries that could "fuzz" objects by seeding the object with garbage values, so not entirely sure how to proceed (or if I should even be wasting my time with this seemingly silly unit test).
Your question goes in a similar direction as the question, whether getters and setters should be unit-tested (see Should unit tests be written for getter and setters?). Your code example for method resetData is, in a sense, even more trivial than setters, because the attributes are assigned constants rather than parameter values.
And, the unit-tests that test the correct setting of the respective attribute would just duplicate that value from the code. The likelihood of findings bugs with such tests is low. And, having a second developer look at the tests is not better than having the second developer review the code itself - a code review would even be a better use of development time. The tests might have a bit of value as regression tests, but again, in most cases where changes are made to the code, the tests have to be maintained just to follow the code changes.
Therefore, similar as for getters and setters and trivial constructors, I would recommend not to write specific tests for resetData, but instead try to make resetData part of some (slightly) larger test scenario by testing the impact of resetData on subsequent computations:
// Setup:
Data data = Data(); // Construction
... // some calculation on data (optional)
// Exercise:
resetData()
... // some calculation on data
// Verify:
...
After all, there should be a reason from a user's perspective why resetData assigns those attributes their specific values. These user focused scenarios could help to make useful tests. (The name resetData, btw., violates the principle of least surprise because people will assume that it resets the values to the initial value.)
The other problem you describe (unit-tests don't tell you that you have not updated resetData if a new attribute was added) indicates you are expecting too much from unit-testing: This phenomenon is not limited to trivial functionality. If you add an attribute and forget to update some complex function to make use of it, plus you leave the tests as they are, then the tests will also continue to pass.
You could think of clever tricks, like, keeping and comparing the list of attributes that were known at the moment the method was written against the current list of attributes (obtained using introspection), but that seems like overkill to me - unless you are developing safety critical code, which I believe dart might not be designed for.
Say I have a class which stores some data in a private variable 'data', e.g. an array. There are different methods of this class using the data variable and different unit tests testing these methods. Now for some reason you want to change the container type of data (e.g. a map instead of an array), which needs to be handled in a slightly different way. If one simply changes the type of data from array to map all the code in the methods gets broken and one would have to change them all before any unit tests can be run again. This usually is not what one wants. So what is the recommended way to do this iteratively without breaking all the code at once ?
Unit tests typically test the outer functionality of a class.
Therefore a refactor of a classes "internals" should not break any tests.
(this is one of the benefits of testing. ).
Many IDE's will allow you to do a automated refactor of internals in one hit. but you did not specify the language or IDE which you are using.
If your class is so large that a change to a data-type creates "hours" of work then you should probably consider breaking your class into smaller bits of functionality prior to a refactor of the data type.
Alternatively you could hand refactor in chunks and attempt to keep the class stable and 'commenting out' the array definition temporarily to help tell you where you need to focus.
This is a followup question on my previous question:
Initialize const members using complex function in C++ class
In short, I have a program that has a class Grid that contains the properties of a 3D grid. I would like the properties of this grid to be read-only after creation, such that complex functions within the class cannot accidentally mess the grid up (such as if(bla = 10), instead of if(bla == 10)) etc. Now, this question has been answered well in the previous discussion: calling an initializer lists via a create function.
Here comes my new problem. My Grid has many properties that just plainly describe the grid (number of grid points, coordinates at grid points etc.) for which it just does not make sense to redistribute them among different objects. Still, basic textbooks in C++ always link functions with a large number of parameters to bad design, but I need them in order to be able to have const member variables.
Are there any standard techniques to deal with such problems?
The answer depends on what you're trying to protect.
If you're trying to assure that users of the class can't inadvertently alter the critical parameters, then the way to do that is to declare these members as private or protected and only provide const getters if they're needed at all outside the class implementation.
If you're trying to assure that the implementer of the Grid class doesn't alter these values, then there a few ways to do so. One simple way is to create a subclass that contains just those parameters and then the answer looks just like 1. Another way is to declare them const in which case they must be initialized when a Grid instance is constructed.
If the answer is 2, then there are also some other things that one can do to prevent inadvertently altering critical values. During the time that you're writing and testing the class implementation, you could temporarily use fixed dummy const values for the critical parameters, assuring that the other functions you write cannot alter those values.
One more trick to avoid specifically the if (i=7) ... error when you meant to write if (i == 7) ... is to always put the constant first. That is, write if (7 == i) .... Also, any decent compiler should be able to flag a warning for this kind of error -- make sure you're taking advantage of that feature by turning on all of the warning and error reporting your compiler provides.
I have created a class that models time slots in a variable-granularity daily schedule, where, for example, the first time slot is 30 minutes, but the second time slot can be 40 minutes and the first available slot starts at (a value comparable to) 1.
What I want to do now is to define somehow the maximum and minimum allowable values that this class takes and I have two practical questions in order to do so:
1.- Does it make sense to define absolute minimum and maximum in such a way for a custom class? Or better, does it suffice that a value always compares as lower-than any other possible value of the type, given the class's defined relational operators, to be defined the min? (and analogusly for the max)
2.- Assuming the previous question has an answer modeled after "yes" (or "yes but ..."), how do I define such max/min? I know that there is std::numeric_limits<> but from what I read it is intended for "numeric types". Do I interpret that as meaning "represented as a number" or can I make a broader assumption like "represented with numbers" or "having a correspondence to integers"? After all, it would make sense to define the minimum and maximum for a date class, and maybe for a dictionary class, but numeric_limits may not be intended for those uses (I don't have much experience with it). Plus, numeric_limits has a lot of extra members and information that I don't know what to make with. If I don't use numeric_limits, what other well-known / widely-used mechanism does C++ offer to indicate the available range of values for a class?
Having trouble making sense of your question. I think what you're asking is whether it makes sense to be assertive about the class's domain (that data which can be fed to it and make sense), and if so how to be assertive.
The first has a very clear answer: yes, absolutely. You want your class to be, "...easy to use correctly and difficult to use incorrectly." This includes making sure the clients of the class are being told when they do something wrong.
The second has a less clear answer. Much of the time you'll simply want to use the assert() function to assert a function or class's domain. Other times you'll want to throw an exception. Sometimes you want to do both. When performance can be an issue sometimes you want to provide an interface that does neither. Usually you want to provide an interface that can at least be checked against so that the clients can tell what is valid/invalid input before attempting to feed it to your class or function.
The reason you might want to both assert and throw is because throwing an exception destroys stack information and can make debugging difficult, but assert only happens during build and doesn't actually do anything to protect you from running calculations or doing things that can cause crashes or invalidate data. Thus asserting and then throwing is often the best answer so that you can debug when you run into it while testing but still protect the user when those bugs make it to the shelf.
For your class you might consider a couple ways to provide min/max. One is to provide min/max functions in the class's interface. Another might be to use external functionality and yes, numeric_limits might just be the thing since a range is sometimes a type of numeric quantity. You could even provide a more generic interface that has a validate_input() function in your class so that you can do any comparison that might be appropriate.
The second part of your question has a lot of valid answers depending on a lot of variables including personal taste.
As the designer of your schedule/slot code, it's up to you as to how much flexibility/practicality you want.
Two simple approaches would be to either define your own values in that class
const long MIN_SLOT = 1;
const long MAX_SLOT = 999; // for example
Or define another class that holds the definitions
class SchedLimits{
public:
const static long MIN_SLOT = 1;
const static long MAX_SLOT = 999;
}
Simplest of all would be enums. (my thanks to the commenter that reminded me of those)
enum {MIN_SLOT = 1, MAX_SLOT = 999};
Just create some const static members that reflect the minimums and maximums.
What is an ObjectMother and what are common usage scenarios for this pattern?
ObjectMother starts with the factory pattern, by delivering prefabricated test-ready objects via a simple method call. It moves beyond the realm of the factory by
facilitating the customization of created objects,
providing methods to update the objects during the tests, and
if necessary, deleting the object from the database at the completion of the test.
Some reasons to use ObjectMother:
* Reduce code duplication in tests, increasing test maintainability
* Make test objects super-easily accessible, encouraging developers to write more tests.
* Every test runs with fresh data.
* Tests always clean up after themselves.
(http://c2.com/cgi/wiki?ObjectMother)
See "Test Data Builders: an alternative to the Object Mother pattern" for an argument of why to use a Test Data Builder instead of an Object Mother. It explains what both are.
As stated elsewhere, ObjectMother is a Factory for generating Objects typically (exclusively?) for use in Unit Tests.
Where they are of great use is for generating complex objects where the data is of no particular significance to the test.
Where you might have created an empty instance below such as
Order rubishOrder = new Order("NoPropertiesSet");
_orderProcessor.Process(rubishOrder);
you would use a sensible one from the ObjectMother
Order motherOrder = ObjectMother.SimpleOrder();
_orderProcessor.Process(motherOrder);
This tends to help with situations where the class being tested starts to rely on a sensible object being passed in.
For instance if you added some OrderNumber validation to the Order class above, you would simply need to instantiate the OrderNumber on the SimpleObject class in order for all the existing tests to pass, leaving you to concentrate on writing the validation tests.
If you had just instantiated the object in the test you would need to add it to every test (it is shocking how often I have seen people do this).
Of course, this could just be extracted out to a method, but putting it in a separate class allows it to be shared between multiple test classes.
Another recommended behavior is to use good descriptive names for your methods, to promote reuse. It is all too easy to end up with one object per test, which is definitely to be avoided. It is better to generate objects that represent general rather than specific attributes and then customize for your test. For instance ObjectMother.WealthyCustomer() rather than ObjectMother.CustomerWith1MdollarsSharesInBigPharmaAndDrivesAPorsche() and ObjectMother.CustomerWith1MdollarsSharesInBigPharmaAndDrivesAPorscheAndAFerrari()