So I have worked through the Money example in Kent Beck's book Test Driven Development by Example and have been able to get the code to work up until the last test that he writes:
#Test
public void testPlusSameCurrencyReturnsMoney(){
Expression sum = Money.dollar(1).plus(Money.dollar(1));
assertTrue(sum instanceof Money);
}
and here is the function that this calls
public Expression plus(Expression addend) {
return new Sum(this, addend);
}
When I run this, it gives java.lang.AssertionError, so my question is why is it giving this error and how do I fix it?
Lunivore already answered the question with how to solve the problem, but I think you should re-read the paragraph just before and after the block of code (and test), if you want to understand more on what Beck was trying to convey.
The last sentence reads "Here is the code we would have to modify to make it work:". That block of code was first entered on page 75 (with test case). Nothing was changed in end effect on page 79. It was just an indication of what we could change, if we wanted to keep this test.
"There is no obvious, clean way to check the currency of the argument if and only if it is Money. The experiment fails, we delete the test, and away we go".
He also stated that this test is ugly and concluded on the following page "Tried a brief experiment, then discarded it when it didn't work out".
I wrote this just in case you were thinking all of the examples just work and should be kept.
You're checking that the sum variable is a Money, but returning a Sum in the plus method.
So, unless Sum is a subclass of Money, that assertion will always fail.
To make it pass, you might want to do something like:
public Expression plus(Expression addend) {
return new Money(...<whatever>...);
}
Of course, Money would then have to be an Expression too.
Or you might want to evaluate the sum to get the money out of it. Or maybe even do sum instanceof Sum instead. It depends on what behavior you're actually trying to achieve.
By the way, beware the instanceof operator.
Related
When looking at some code on one or another git, sometimes I can see that devs use bitwise inclusive OR compound assignment operator (|=) where simple assignment would be enough. Unfortunately, I don't have any code with this solution at hand, so I'll try to describe it as best I can.
Let's say, we have the following code in java:
boolean found = false;
for (String s : stringSet) {
if (s == null || s.equals("")) {
found |= true; // <== this line
}
}
if (!found) {
System.out.println("No interesting string found");
}
I ask only about the pointed line. Why people do it this way? I understand that we can have a really great amount of data, billions or trillions to iterate over. But does the pointed line changes the efficiency so dramatically? Would it be noticeably slower for a lot of data, if I change it to simple assignment: found = true;?
I don't exclude the possibility that not a speed is the main argument, but it seemed most meaningful to me.
And yes, I know this code can be converted to method or streams, but it's only a simplification of a code where it would be far more complicated etc. We can assume that before the pointed line (or even before if), there are tons of code that do something meaningful. Please, don't suggest something like "use streams instead", because I know how to java advanced already. I'd like to understand the phenomenon of this somehow enigmatic solution using bitwise inclusive OR.
I have a section of code that does a running count of payments to see if rent has been paid for a property, code is as follows:
BigDecimal remainingAmount = MathUtilities.roundBigDecimal(new BigDecimal(amountDue.getAmount().doubleValue()));
for(RentPayment payment : this.rentPayments) {
remainingAmount = remainingAmount.subtract(payment.getAmountPaid().getAmount());
}
return remainingAmount;
So here, all that needs to happen is remaining amount needs to be returned so we know how much rent has been paid for a particular invoice. When I run this in the debugger, it does 235.66 - 235.66, with the logical result of 0:
remainingAmount.subtract(payment.getAmountPaid().getAmount());
However, when running this code normally, the result, no matter how many payments of 235.66, is always 235.66, event though I'm explicitly setting remainingAmount. Is there something I'm missing? Every question I've looked at seems to suggest I'm doing this correctly.
Edit: Just to show I'm not crazy or missing something obvious:
And:
The issue was because a watch I had used to validate the result of the operation was left in and it was overriding what my code was doing, this was a simple user error, closing out this question.
I saw the following code in this commit for MongoDB's Java Connection driver, and it appears at first to be a joke of some sort. What does the following code do?
if (!((_ok) ? true : (Math.random() > 0.1))) {
return res;
}
(EDIT: the code has been updated since posting this question)
After inspecting the history of that line, my main conclusion is that there has been some incompetent programming at work.
That line is gratuitously convoluted. The general form
a? true : b
for boolean a, b is equivalent to the simple
a || b
The surrounding negation and excessive parentheses convolute things further. Keeping in mind De Morgan's laws it is a trivial observation that this piece of code amounts to
if (!_ok && Math.random() <= 0.1)
return res;
The commit that originally introduced this logic had
if (_ok == true) {
_logger.log( Level.WARNING , "Server seen down: " + _addr, e );
} else if (Math.random() < 0.1) {
_logger.log( Level.WARNING , "Server seen down: " + _addr );
}
—another example of incompetent coding, but notice the reversed logic: here the event is logged if either _ok or in 10% of other cases, whereas the code in 2. returns 10% of the times and logs 90% of the times. So the later commit ruined not only clarity, but correctness itself.
I think in the code you have posted we can actually see how the author intended to transform the original if-then somehow literally into its negation required for the early return condition. But then he messed up and inserted an effective "double negative" by reversing the inequality sign.
Coding style issues aside, stochastic logging is quite a dubious practice all by itself, especially since the log entry does not document its own peculiar behavior. The intention is, obviously, reducing restatements of the same fact: that the server is currently down. The appropriate solution is to log only changes of the server state, and not each its observation, let alone a random selection of 10% such observations. Yes, that takes just a little bit more effort, so let's see some.
I can only hope that all this evidence of incompetence, accumulated from inspecting just three lines of code, does not speak fairly of the project as a whole, and that this piece of work will be cleaned up ASAP.
https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225#commitcomment-3315694
11 hours ago by gareth-rees:
Presumably the idea is to log only about 1/10 of the server failures (and so avoid massively spamming the log), without incurring the cost of maintaining a counter or timer. (But surely maintaining a timer would be affordable?)
Add a class member initialized to negative 1:
private int logit = -1;
In the try block, make the test:
if( !ok && (logit = (logit + 1 ) % 10) == 0 ) { //log error
This always logs the first error, then every tenth subsequent error. Logical operators "short-circuit", so logit only gets incremented on an actual error.
If you want the first and tenth of all errors, regardless of the connection, make logit class static instead of a a member.
As had been noted this should be thread safe:
private synchronized int getLogit() {
return (logit = (logit + 1 ) % 10);
}
In the try block, make the test:
if( !ok && getLogit() == 0 ) { //log error
Note: I don't think throwing out 90% of the errors is a good idea.
I have seen this kind of thing before.
There was a piece of code that could answer certain 'questions' that came from another 'black box' piece of code. In the case it could not answer them, it would forward them to another piece of 'black box' code that was really slow.
So sometimes previously unseen new 'questions' would show up, and they would show up in a batch, like 100 of them in a row.
The programmer was happy with how the program was working, but he wanted some way of maybe improving the software in the future, if possible new questions were discovered.
So, the solution was to log unknown questions, but as it turned out, there were 1000's of different ones. The logs got too big, and there was no benefit of speeding these up, since they had no obvious answers. But every once in a while, a batch of questions would show up that could be answered.
Since the logs were getting too big, and the logging was getting in the way of logging the real important things he got to this solution:
Only log a random 5%, this will clean up the logs, whilst in the long run still showing what questions/answers could be added.
So, if an unknown event occurred, in a random amount of these cases, it would be logged.
I think this is similar to what you are seeing here.
I did not like this way of working, so I removed this piece of code, and just logged these
messages to a different file, so they were all present, but not clobbering the general logfile.
I am not looking for the answer to this question but just a brief outline of how to do it. This is a question from a exam past paper.
It states: Describe in English a sequence of tests that you might use to test code to implement the NumberCoversion class. Your tests should cover all the conditions described in the above definition.
I won't write the specification of the class but it contains things like: it must take String as input and output, accepting two parameters and returning null if a number is not valid etc.
The question is worth 10% so will I just be required to write a series of things like: Ensure that the constructor only accepts two parameters of type int, and not anything else e.g. double or accept 3 parameters.
Would it be worth writing possible JUnit test methods in English/Pseudocode.
Would this be the right sort of thing to write for tests in English?
I think the goal is to describe a test case which checks each of the specifications in the question, whilst also avoiding attempting to test things which are limited by the language construct (e.g. wrong number/type of arguments).
Describe in English what you will do if you write tests. Typically it's usage of the NumberConversion class.
According to the question, you need to describe tests in English. I think that jumping to JUnit unit tests is more than being asked for. If I answered this question, I would start by looking at the definition given of the NumberConversion class. I would describe tests that use valid inputs as well as tests that use invalid ones. For each test describe how you will ensure that the NumberConversion class behaves as expected, including expected error conditions.
As an example for what might be appropriate...
If the specifications were:
Takes a string as input
The string can be an arbitrarily large non-negative integer
If the string is not a non-negative integer, an exception is thrown
Then I would probably answer something along the lines of:
I would test with "42" as input to check that the method works with a "normal" number
I would test with "0" as input to check that the method works with the edge case number
I would test with "9223372036854775808" (1 more than Long.MAX_VALUE) as input to check that the method works with a number larger than the fixed length integers provided by Java
I would test with "-1" as input and ensure that an exception is thrown, as negative input is invalid
I would test witht "0xa" as input and ensure that an exception is thrown, as hexadecimal input is invalid
I would test witht "0.1" as input and ensure that an exception is thrown, as non integral input is invalid
I have a question which is described below:
What problems would arise for testing a Java class which counts number of words in a file?
The function's signature is below:
public int wordCount(String filename)
Well, this is a junit testing question.
If you know the problem, what is the solution of that?
So your question is what to test for? If yes, I'd say you should check if the definition of "word" is implemented correctly (e.g. is "stack-overflow" one word or two), are new lines handled correctly, are numbers counted as words (e.g. difference between "8" and "eight"), are (groups of special) characters (e.g. a hyphen) counted correctly.
Additionally, you should test whether the method returns the expected value (or exception) if the file does not exist.
This should be a good starting point.
To sfussenegger's list, I'd add the file handling checks: does the method respond correctly to files not found (including null filename), or lacking read permission?
Also, to sfussenegger's correctness list, I'd add whether duplicates count and case sensitivity rules, as well.
Of course, all of this requires that you know how the method is supposed to behave for all of these specifics. It's easy to tell someone to "go count words", but there are subtleties to that assignment.
Which is one of the big benefits of writing a good set of unit tests.
This really sounds like a task for FIT: Framework for Integrated Test. It's an acceptance testing framework that works with ant and JUnit.
One docent of mine did such a task and used this framework. It allows you to write a whole bunch of test cases within one html/wiki table. FIT will interpret each line as a parameter set for the function under test and checks the output.
For example:
This table displays the result of three test cases. Two passed, one failed.
You can use fit if you write sentences and define the number of words in your table. With FIT, they're executed and the result is displayed in a new table.
For further information, please read Introduction to FIT.