• 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
  • Bear Bibeault
  • Devaka Cooray
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • paul wheaton
Saloon Keepers:
  • Ganesh Patekar
  • Frits Walraven
  • Tim Moores
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Stephan van Hulst
  • salvin francis
  • Tim Holloway

Help with JUnit  RSS feed

 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I tried to start the test this way. How does it look ?



The validator looks like this:



Obviously, the second test fails due to IllegalArgException.

Am I heading in the right direction ?
Should I have created the string test before the null test ? Does order matter ?

Thanks !
 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Assuming that I am headed in the right direction, this is what PasswordValidator looks like:


 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Refactoring the least code and checking if the tests still pass, which they do.


 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Removing the redundant check for instance of string.



This will cause the empty string test to fail. I don't know if I am headed in the wrong direction now or if TDD is just complicating things for me.
 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fix to make empty string pass:


 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Making the null test pass, running around in circles with TDD.



 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
removing the second if check.



 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Refactoring the tests. We could have used null string instead of the null object to begin with and avoid all these steps.



Btw, there is no assertion in that empty string test, which feels wrong because the test is not really asserting/checking anything. Moreover, the test name is a bit vague.
Deleting all code and starting from scratch. This is crazy. I wonder how low we have to go with this TDD thing.
 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I take that back. I am only going to delete the useless empty string test because it checks nothing. My tests:



Fixing the compiler error due to last line.




 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
we now test:


 
Jay Moore
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To make it pass:


 
Saloon Keeper
Posts: 2153
278
Android Angular Framework Eclipse IDE Java Linux MySQL Database Redhat TypeScript
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why not just return a boolean value indicating if the password is valid or not?:
 
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It looks like you're caught up in the mechanics of Red-Green-Refactor and not thinking about the actual design of the API of your class. This causes you to flail around looking for tests to write and things to refactor. It all feels silly when you do TDD this way.

TDD is a very intentional design-focused technique. It's not about testing. Tests are just nice-to-have side-effects of the design process, artifacts that should relate the story that you're trying to tell about the production code you wrote.

Start with thinking things like:
"If the Validator was asked to validate a null value, what should it do? What should the client code look like? Is that the kind of code programmers who use the Validator class would like to write? Does it make sense? Are the semantics intuitive?"

"If the Validator was asked to validate an empty string, what should it do? What should the client code look like? Is that the kind of code programmers who use the Validator class ... yada yada yada"

"If the Validator was asked to validate a good password, what should its return value be? What would the client code look like? Is this the kind of code ... yada yada yada"

"If the Validator was asked to validate a password that was too short, yada yada yada ... "

"If the Validator was asked to validate a password that didn't have at least one digit, ... "

"If the Validator ... "

All these questions lead you to thinking about what client code that uses the Validator class should do and how it should be written so that it's clear and it makes sense when you read it. That's what you should write in your tests, examples of how the Validator class should be used in client code. Then you add assertions to make sure that what you think should happen actually did happen.

 
Junilu Lacar
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's what I've been teaching people lately:

Uncle Bob has given Three Laws of TDD

1. You are not allowed to write any production code unless it is to make a failing unit test pass.
2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

These laws only make sense if:
1. You're using tests to drive emergent design and subscribe to the idea that tests are detailed design specifications.
2. You're developing code incrementally and subscribe to the idea that tests are examples of how your class should be used.
3. You're refactoring ruthlessly to keep the code clean at all times and you subscribe to the idea that "The only way to go fast, is to go well."
 
Junilu Lacar
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As far as refactoring, keep the Four Rules of Simple Design in mind:

1. All the tests pass
2. Code clearly states intent
3. There is no duplication
4. Things are small

 
Junilu Lacar
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jay Moore wrote:


I would question why you'd want to design the API this way. I'd experiment with different ways to design this. What string do you return when a password is valid? What's the code going to look like? Do you mean I'd have to write something like this:

That's kind of icky because the semantics aren't very good.

This might be an alternative I'd want to explore:

or something else entirely.
 
Junilu Lacar
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another thing to watch for when you're doing TDD is that your design decisions and refactoring should make it easy to see, in fact almost obvious, what the next test to write should be. This has a lot to do with semantics, i.e. what the code you write means to you when you read it. You want to look for consistency and coherence in the semantics of the test code and in the production code. You want the tests and the production code to tell you want it wants to do next.

Take my previous example. If I design the API so that I had to write the client code like that, it's very easy for me to see what the test code wants to be:

and that leads me to the converse test:

These two tests have a nice symmetry to them and they make sense to me when I read them.
 
Junilu Lacar
Sheriff
Posts: 12748
210
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jay Moore wrote:The validator looks like this:


Again, I have to question the design choice made here. Why design this method to accept an Object parameter? Are passwords really going to be anything other than String? This initial step and the semantic problems with it is another thing that tells me you're probably just thinking about the mechanics of Red-Green-Refactor and not really about using the tests to explore a possible design choice and do some experiments with it.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!