When testing class methods, occasionally I need to compare the returned value to some constant defined in some class.
class FooBar
{
const RANDOM = 18;
}
....
// Somewhere in test...
$this->assertEquals(FooBar::RANDOM, $mock->doSomething());
Now as since PHP 7.1 it is possible to define class constants with visibility modifier, this could be changed to:
private const RANDOM = 18;
However, that stops the test from working, as now we are trying to access private constant.
So now we have two options:
Declare the constant as public.
Use reflection in test. Meaning the test becomes:
$this->assertEquals(
(new ReflectionClass(FooBar::class))->getConstant('RANDOM'),
$mock->doSomething()
);
The first approach feels very wrong, as we are making constant public only for the sake of test, not because class/hierarchy/business model needs it to be public.
The second one doesn't feel right either, as this use case would not be found
by any IDE, so any search/replace/refactor would simply fail here.
So my question(s) is, should the second scenario be used without caring that refactoring will break tests? Or maybe even the use of constants in general should be discouraged in asserts?
Using the constant in test is actually a bad practice IMHO.
You should test the constant's literal value. ($this->assertSame(18, $mock->doSomething())
Why?
Because one of the important values testing brings you is that you notice unintended consequences of changes to the code. As the constant is private it's value is never used outside of the class. But many different things may depend on it's value internally.
Now imagine a junior developer, who is not familiar with the codebase is tasked with changing one of the places where the constant is used and change it from 18 to 16. He will go and change the constant's value from 18 to 16 and do a rough check of where the constant is used (not noticing your doSomething() method). Now, in your method you absolutely need the random to be 18, not 16! But if you used the constant, he'd never know, because as he changed it from 18 to 16 the assert would also change from 18 to 16. And the test would pass.
Rule of thumb for me:
Never use expected value of assert that is pulled from the code of the
app. Always use literal value where possible.
Related
Looking at our code base, I see many cases, where fields of derived types make you expect them to remain unchanged once initialized and ideally, to be initialized all at once and never changed afterwards (like a "value type").
In practice, quick solutions have built up, such that whether a field changes or even what it contains may depend on the code path, leading to large IF-ELSE cascades everywhere, making the code hard to follow and brittle against changes.
This made me wonder: Is it possible to enforce constraints such as immutability of fields?
you can use the "parameter" key word to make a variable a constant.
https://www.tutorialspoint.com/fortran/fortran_constants.htm
real, parameter :: g = 9.81
You would have to know the values at compile time so this may not be what you're looking for. If it's not, could you give us some clarification and we can try to help you?
************EDIT******************
As others have stated above, if you need to be able to set the variable at runtime, then getters and setters are the way to go.
You can either make the variable private and write a getter and a setter for it or if you make the variable protected then you only need to write a setter for it.
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.
This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 9 years ago.
I've been told not to make my variables public inside a class. I should always make a get and a set function. For example :
class Whatever
{
public:
void setSentence(const std::string &str) { sentence = str; }
void setAnInteger(const int integer) { anInteger = integer; }
std::string getSentence() { return sentence; }
int getAnInteger() { return anInteger; }
private:
std::string sentence;
int anInteger;
};
Why should I do that? Isn't just simply using those variables more convenient? Also, is that a good c++ programming style?
The main reason is to increase encapsulation. If your class exposes those member variables, many functions in your client code will have a dependency towards those variables.
Suppose one day you want want to change the name of those variables, or you want to change the implementation of your class so that the type and number of member variables would be different than the current one: how many functions would be affected by this change? How many functions would you have to re-write (at least in part)?
Right, potentially infinite. You just can't count them all. On the other hand, if you have getters and setters, only those 4 functions will have access to the internal representation of your class. Changing the internal representation won't require any change to the code of your client functions; only those 4 member functions may have to be changed.
In general, encapsulation makes your life easier with respect to future changes. At a certain point in time you may want to log a message every time a certain property is set. You may want to fire an event every time a certain property is set. You may want to compute a certain value on the fly rather than reading it each time from a cache data member, or read it from a database, or whatever.
Having getters and setters allow you to implement any of those changes without requiring to change the client code.
As far as general design philosophy is concerned, there is no "always" or "never" when it comes to implementing accessors versus not implementing accessors that the community as a whole agrees on.
Many will advise you to make all data members private and provide accessors & mutators. Always.
Others will tell you to make data members private if changing them from client code is undesirable, and leave them public otherwise.
Yet others will tell you that classes shouldn't have more than one or so data member at all, and all the data should be encapsulated in yet another object, preferably a struct.
You have to decide for yourself which is right, keeping in mind that this will depend not only on your approach, but also that of the organization for which you work.
If you ask me, my preference is to make everything public until I have a reason not to. Simple. But that's just me.
You write explicit getters and setters as a sane plan for future development. If your class' users are directly accessing its members and you need to change the class in a way that is incompatible with that habit, you have to change every chunk of code that interfaces with you in this way. If you write a getter and setter, the compiler will optimize it to be time-equivalent to direct access (if that is all it does) and you can later change the logic if you need to - without having to change a ton of other code.
When you make get or set method and use it 40 times in your code, you can handle future changes more easily.
Imagine, that you use public variable and use it 40 times in your code. After a month of developing your program, you'll come up with a great idea: What if I divide this variable by 1000 and so I would have better values to calculate with!
Wow, great, but now I have to find every single line, where I use it and change it. If I only had a get method :(
That's the main reason of getters and setters, even if they are very simple, it's better to have it. You will thank yourself once.
Data encapsulation is one of the major principles of OOP. It is the process of combining data and functions into a single unit called class. Using the method of encapsulation, the programmer cannot directly access the data. Data is only accessible through the functions existing inside the class so that the implementation details of a class that are hidden from the user. It's to protect both the caller and the function from accidentally changing the behavior of a method, or from needing to know how a method works.
The textbook-ish answer recalled from me taking the first OOP class was: Get and set methods are used to wrap around private variables. Usually people compare between having get and set or just simply set those variables to be public; in this case, get and set approach is good because it protects those variables from being modified accidentally due to bugs and etc..
People (me when I took that class) might ask "isn't get and set also modify those variables, if so, how is that different than being modified as a public variable".
The rationale is: to have get and set function, you are asking the user or yourself to explicitly specify they want to modify the variable by calling those functions. Without calling those functions, the private variables will be less likely (still possible depends on implementation) modified unwillingly or accidentally.
In short, you should not do that.
In general, I suggest to read Fowler's Refactoring, then you will have a picture what gets hindered by having naked data, and what kind of access aligns well. And importantly whether the whole thing applies to your cases or not.
And as you know pros&cons you can safely ignore "should do/don't" stuff like at start of this answer or others.
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.
For example this article introduces them.
What is the benefit?
Static analysis seems cool but at the same time it would prevent the ability to pass null as a parameter in unit test. (if you followed the example in the article that is)
While on the topic of unit testing - given how things are now surely there is no point for code contracts if you already practice automated testing?
Update
Having played with Code Contracts I'm a little disappointed. For example, based on the code in the accepted answer:
public double CalculateTotal(Order order)
{
Contract.Requires(order != null);
Contract.Ensures(Contract.Result<double>() >= 0);
return 2.0;
}
For unit testing, you still have to write tests to ensure that null cannot be passed, and the result is greater than or equal to zero if the contracts are business logic. In other words, if I was to remove the first contract, no tests would break, unless I had specifically had a test for this feature. This is based on not using the static analysis built into the better (ultimate etc...) editions of Visual Studio however.
Essentially they all boil down to an alternate way of writing traditional if statements. My experience actually using TDD, with Code Contracts shows why, and how I went about it.
I don't think unit testing and contracts interfere with each other that much, and if anything contracts should help unit testing since it removes the need to add tedious repetitive tests for invalid arguments. Contracts specify the minimum you can expect from the function, whereas unit tests attempt to validate the actual behaviour for a particular set of inputs. Consider this contrived example:
public class Order
{
public IEnumerable Items { get; }
}
public class OrderCalculator
{
public double CalculateTotal(Order order)
{
Contract.Requires(order != null);
Contract.Ensures(Contract.Result<double>() >= 0);
return 2.0;
}
}
Clearly the code satisfies the contract, but you'd still need unit testing to validate it actually behaves as you'd expect.
What is the benefit?
Let's say that you want to make sure that a method never returns null. Now with unit tests, you have to write a bunch of test cases where you call the method with varying inputs and verify that the output is not null. Trouble is, you can't test all possible inputs.
With code contracts, you just declare that the method never returns null. The static analyzer will then complain if it is not possible to prove that. If it doesn't complain, you know that your assertion is correct for all possible inputs.
Less work, perfect correctness guarantees. What's not to like?
Contracts allow you say what the actual purpose of the code is, as opposed to letting whatever the code does with whatever random arguments are handed it standing as the definition from the point of view of the compiler, or the next reader of the code. This allows significantly better static analysis and code optimization.
For instance, if I declare an integer parameter (using the contract notation) to be in the range of 1 to 10, and I have a local array in my function declared the same size, that is indexed by the parameter, the compiler can tell that there is no possibility of subscript error, thus producing better code.
You can state that null is valid value in a contract.
The purpose of unit testing is to verify dynamically that the code achieves whatever stated purpose it has. Just because you've written a contract for a function, doesn't mean the code does that, or that static analysis can verify the code does that. Unit testing won't go away.
Well it will not interfere with unit-testing in general. But as I saw you mentioned something about TDD.
If I think about it from that perspective I guess it could/may change the procedure from the standard one
create method (just signature)
create Unit test -> implement the test
run the test: let it fail
implement the method, hack it to the end just to make it working
run the test: see it pass
refactor your (possibly messy) method body
(re-run the test just to see you've not broken anything)
This would be the really hard-full-featured unit-testing procedure. In such a context I guess you could insert code contracts between the 1st and 2nd point like
create method (just signature)
insert code contracts for the methods input parameters
create Unit test -> implement the test
...
The advantage I see at the moment is that you can write easier unit tests in the sense that you wouldn't have to check every possible path since some is already taken into account by your defined contracts. It just gives you additional checking, but it wouldn't replace unit testing since there will always be more logic within the code, more path that have to be tested with unit tests as usual.
Edit
Another possibility I didn't consider before would be to add the code contracts in the refactoring part. Basically as additional way of assuring things. But that would somehow be redundant and since people don't like to do redundant stuff...