Win a copy of Transfer Learning for Natural Language Processing (MEAP) this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Paul Clapham
  • Devaka Cooray
  • Bear Bibeault
Sheriffs:
  • Junilu Lacar
  • Knute Snortum
  • Liutauras Vilda
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Tim Holloway
  • Piet Souris
Bartenders:
  • salvin francis
  • Carey Brown
  • Frits Walraven

Unit Testing

 
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi there

I'm learning about unit testing at the moment, finding it difficult enough, I was looking through some of my old project and decided to practice writing unit tests for some of the methods, one of which was just a simple pay calculator, I'm a bit confused and need guidance, how would  I unit test a method with  if branches? like the one below






Please note the total value is calculated in the method below

 
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Write a test for each branch.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You generally want to write unit tests for just the public methods. If you test those thoroughly, any methods that are called indirectly through the public API are also indirectly tested.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is very strange: this.getHIGHER_TAX_RATE()

What it suggests to me is that you've created an accessor method for a constant value. Don't do that. If you have a symbolic constant HIGHER_TAX_RATE, then refer to it directly as such. You're just polluting your class with a pointless getter.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your unit tests might look something like this:

Which leads you to question why do you have two different branches, 601-1300, and the else catchall that use the same formula.

There's also something off with the way calculateTax() both sets the tax field and returns the value you've just calculated for it. Do one or the other, not both.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The way you've written the calculateTax() method also suggests these tests:

Is this what you intended the behavior to be? That you would round off the tax in some cases and not for others? Because that's what your code does.
 
Kevin O'Sullivan
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks so much for you're help and guidance, I'll try to write a test there now in a min and post back later.
 
Kevin O'Sullivan
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:The way you've written the calculateTax() method also suggests these tests:

Is this what you intended the behavior to be? That you would round off the tax in some cases and not for others? Because that's what your code does.



I wanted the total tax to rounded to the nearest decimal place for all cases.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Kevin O'Sullivan wrote:I wanted the total tax to rounded to the nearest decimal place for all cases.


Then you should be able to write a unit test that captures that idea and see it fail because your code doesn't do that right now.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One thing I teach programmers to do is to change your mindset so that you see a failing test as a thing to celebrate. A failing unit test means that you've just found another bug and you know exactly what needs to be fixed. If you are writing tests before you write the actual code to make it pass (that is, programming in a TDD style) a failing test is actually an indication of progress. It means now you can go write some production code that makes the failing test pass. The mindset is "There, the test failed.   Now I can go write the code to make it pass and get closer to being done!"

This is in stark contrast to writing tests after the fact, where a failing test usually makes you think "Dang it, I'm not done after all."

Programming is a lot more fun when you're doing this instead of this   or this  .
 
Kevin O'Sullivan
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I changed some things around but ultimately I'm still stuck I only have two branches now







So I created a test just to see if the right tax amount was being calculated but its only returning 0 instead of the expected value, so the test is failing and I can't figure out why





org.opentest4j.AssertionFailedError:
Expected :75.0
Actual   :0.0





 
Marshal
Posts: 68917
275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Put a line in at the beginning of the calculate tax method to print out the total pay at that moment.
You have hit a general problem with having too many fields. (Well, maybe that's what caused it.)
 
Kevin O'Sullivan
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Put a line in at the beginning of the calculate tax method to print out the total pay at that moment.
You have hit a general problem with having too many fields. (Well, maybe that's what caused it.)



You mean like this ?


 
Campbell Ritchie
Marshal
Posts: 68917
275
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes. You might do well to print the w‍ord “tax” too.
 
Kevin O'Sullivan
Ranch Hand
Posts: 61
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Yes. You might do well to print the w‍ord “tax” too.



Still the same result I'm afraid.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You won't change the result by adding a System.out.println() statement. The idea there is to "debug" and see what's going on. Sometimes this approach is helpful, sometimes it isn't. If you really want to learn how to use tests to help you find mistakes and bugs, then write a very targeted test that will fail only when a mistake is made in a particular area of the code.

Also, you haven't been giving us much context with the code you've posted so far. It might help if you post more code. For example, this is kind of horrific:

We have no idea what any of those arguments to the constructor even mean. Which of those values actually get involved in calculating the tax and tax rate? Also, I doubt the test name "test_calculateLowerTaxRate" accurately captures the actual intent of the test and what the code in it is doing. Get your head out of "implementation mode" and concentrate on "intent" first. Then make your code reflect that intent so it's clear to you and to others what you're trying to accomplish. Only with that kind of clarity will it be easier to find where the mistake/bug has been made.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
By the way, what unit testing framework are you using? I expected JUnit since that's the de facto but it looks like you've got openTest4j assertions judging from what you posted.
 
Junilu Lacar
Sheriff
Posts: 15525
263
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So a few things I can see going wrong here.

If you expect the test to hit these lines of code:

then the following can contribute to getting a result of 0.0:

1. total might be 0
2. LOWER_TAX_RATE might be 0
3. the calculated value for tax might be less than 0.5. Since Math.round(double) actually returns a long value, it will return 0L if the argument you pass to it gets rounded down, 1L if it gets rounded up. It doesn't matter that you declare the method to return a double. The long 0 or long 1 you get back from Math.round() will be promoted automatically to a double but it will still have the value of 0.0 or 1.0.
 
Campbell Ritchie
Marshal
Posts: 68917
275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:You won't change the result by adding a System.out.println() statement. The idea there is to "debug" and see what's going on. . . .

It might have been better if I had told him to print the right thing (sorry ). Please print the total earnings at the same point.
 
Good heavens! What have you done! Here, try to fix it with this tiny ad:
Try Free Java/.NET Libraries for Word Excel PowerPoint and PDF
htttp://www.e-iceblue.com/free-apis.html
    Bookmark Topic Watch Topic
  • New Topic