Vishwanath Krishnamurthi's blog

A blog on Java EE, clean code, open source and TDD

Archive for the ‘Design’ Category

Failing Fast / Assertive Programming

leave a comment »

I am not using this term “assertive programming” strictly on the basis of  using “assert” keyword, but a little loosely, to  fail-fast and expose bugs early. It is a great technique for programmers to shorten their debugging-time, but hardly do I ever see any ‘asserts’ in codebase.

Languages like Eiffel contain constructs for preconditions and postconditions and goes a step further in helping to program assertively, but at least we’ve got an “assert” keyword in Java.

Here is a nice usage of assert, I found in a merge-sort implementation.  The merge step merges two sorted halves into one.

For this to work correctly, the two halves must be sorted.


merge(int []a, int aux[], int low, int mid, int high)
{
assert isSorted(a,low,mid);
assert isSorted(a,mid+1,high);
// rest of the merging code
}

What better way to document our expectations and to expose the bugs early on ?

There are a couple of choices when it comes to “ways of asserting”

The assert keyword is handy, throws error on failing and could be switched off at production. The other way is to go towards an API (Spring-Assert, GoogleGuavaPreconditions) or a custom-class,that throws an Exception

but regardless of the ways, assertion as such is a great tool, not to be disregarded.

Assertions aren’t the only ways ensure ‘Fail Fast’. For example, when using transaction attributes, you could ensure that a transaction must be present using ‘mandatory’ rather than using a ‘required’ and stay away from a vague transaction attribute like ‘supports’

While working with read-only values, you could use something from the programming language to ensures it. Marking references as, ‘final’, better yet, using Immutable objects, would go towards it.

So, hey ! Go assert !

Good Reads:

Here’s a very good article on “failing fast“.

To assert or not to assert

Written by Vishwanath Krishnamurthi

December 9, 2012 at 11:57 am

A few things to avoid while writing unit tests

with 2 comments

Long back I wrote a post on some good practices to follow while writing unit tests.  I thought I’d add one on mistakes/practices to avoid while writing unit tests.

1) Reading a configuration file:

If for writing a unit test, you access a file, then strictly speaking, it is not a unit test.

For example,

class CarTest
{
Engine engine;
// your test for engine object
}

If you created the object under test by doing,

Engine engine = new Engine();

that’s neat. Whereas if DI was used to create the ‘engine’ object, then it wouldn’t have been a unit test. (DI involves reading an external file/ scanning for annotations )

Likewise, if for test data, you retrieved the data from a file, then its not really a unit test.

the main drawback being ?

Reading files takes time. A unit test has to be really fast. Something that’s executed very often.

2) Mocking the wrong objects:

Mocking frameworks are great.  You could easily mock a ‘dao’ or a ‘service’ call and write a unit-test quickly. Mocking a ‘value-object’ like the one above is needless.

public void  AccountBalanceTest
{
@Mock AccountInfo accountInfo;
@Test
public void  debitShouldDecuctTheGivenAmount()
{
when(accountInfo.getCurrentBalance()).thenReturn(500);
Account account = new Account(accountInfo);
account.debit(100);
}
}

It turns out to be messy when a lot of such stub values are defined.

‘Value-Objects’ being easily constructible with a ‘new’ should rather be used like this:

@Test
public void  debitShouldDecuctTheGivenAmount()
{
AccountInfo accountInfo = new AccountInfo();
accountInfo.setCurrentBalance(500);
Account account = new Account(accountInfo);
account.debit(100);
}
}

This reads a lot better, doesn’t it? And when there are a lot of test data to be prepared, there’s of course the very useful builder pattern http://nat.truemesh.com/archives/000714.html

3) Ignoring the feedback

A great thing about writing tests is that you get “feedback” about your code.

For example,  if you started writing a test like this,

@Test
public void testValidateAddressShouldCheckForMandatoryPostCode()
{
Customer customer = new Customer();
Address address = new Address();
address.setPostCode("123456");
customer.setAddress(address);
Validator validator = new Validator();
validator.validateAddress(customer);
}

you should be seeing a “warning” here. You’re spending some effort constructing the object required for test,

and this “warning” should hint you that, the validateAddress() method should be refactored to take an address parameter and not a customer parameter.

It is easy to set up the object like above and get the test passing – but that’s not the point. The idea should be to take the feedback and refactor.

@Test
public void testValidateAddressShouldCheckForMandatoryPostCode()
{
Address address = new Address();
address.setPostCode("123456");
Validator validator = new Validator();
validator.validateAddress(address); // refactored method.
}

Yes, the above one was a simplified example, but hope the idea is clear.

Similarly, when a piece of code is hard to test, it is possible to overcome the pain by using some advanced mocking frameworks and finishing up the test. But “being hard to test” might be a feedback telling  you to take efforts to refactor the code and make it testable/loosely-coupled.

Here’s a great post http://martinfowler.com/articles/modernMockingTools.html that explains it.

So to put it again, “the feedback should not be ignored”

 

Good TDD resources

http://misko.hevery.com/
http://www.growing-object-oriented-software.com/
http://vimeo.com/10569751

 

Written by Vishwanath Krishnamurthi

April 9, 2012 at 11:49 pm

Posted in Design

Tagged with , ,

Unit Test – What matters ? And some good practices

with one comment

Unit testing – Framework matters ? – No. Not much

Just as any “framework” is supposed to do, unit testing frameworks simplify your job and that’s what they are for. You could get the hang of a framework like JUnit in just a few minutes.

Unit testingWriting hundreds of tests matters ? – No. Not Unless

these tests are “good quality tests”. It’s pretty easy to write hundreds without having a sense of what these tests are supposed to test.
What matters is having “good quality” unit tests. So what makes a test, a good one ? Well I would say that of all factors, “failability” is the most important one.

To explain, say you’ve written a test of requirementX. A few days later the requirement changes and you make the code changes without changing the test. On running the test, the test should fail. If it doesn’t the test was no good at all.

Unit testingWriting testable code matters ? – Hell yes !

More than anything ! Writing testable code matters so much. And probably the best material around on the net would be http://misko.hevery.com/

Unit testing – Discipline matters ? – Yes ! The most difficult one to acquire

We do come up with excuses for not writing tests. “Pressure”, “Deadlines” and more. And yes, as previously said, those are “excuses” for our own laziness.

Developing this discipline and sticking to it is probably the hardest thing to do. Definitely, I know I don’t have this discipline. But this is something to work towards. There’s a great section on Uncle Bob’s book “Clean Code” on how a developer should guard his code, writing tests, without excuses. You might like reading it.

The good practices section – Okay, just a collection of advises that you’d normally find

  • Focus on writing tests that cover only “one unit” so that a twenty tests don’t break in the place where only one should have broken. http://www.javaranch.com/journal/200603/Journal200603.jsp
  • Must not depend on the order in which a test is run. (Eg: A test should not expect a particular test to have run before it. )
  • If your method can behave in two different ways (say based on the value of a parameter passed), write two different unit tests.
  • Learn when / how to use mock libraries. (Mockito is a good one! )
  • Check the coverage of your tests once in awhile. (There are some amazing coverage plugins ) It’s good to have 70-80% coverage
  • Check also the exception paths and write separate unit tests for exception paths
  • Have minimal no of asserts in a test -Ideally one. Having one assert per test makes the test standalone and also precisely pin points the bug.
  • To check an algorithm, use a second algorithm and verify for matching results. ( Eg: you can check your sort() method that does a heap-sort by writing a sort() method in your test class that does a bubble-sort. And verify that both algorithms return the same results )
  • Need not test very simple code – getters, setters or very basic methods
  • Let the test names be long and descriptive – Describe the expected behavior. A mere testMethodX() is not of much use. methodXShouldDoYWhenPassedZ() helps.
  • Object Oriented design practices, clean code, good naming, refactoring – All of these apply here too -The test documents the design. Hence using right method names is extremely important. To understand a functionality, a programmer would first want to read and execute a test !
  • Need not test private methods. If the private methods are not very complicated, they need not be tested. A private method can be tested indirectly by testing the public/package-private methods that use it.
  • A bug is reported ? Write a test. Result is red ? Good. Now add the fix and make it Green.

Finally, Why TDD ? And why “test first” as advocated by TDD ?

TDD advocates that a test should be written and only then production code is written. A not-so-intuitive thing to do. But what is the gain ? By writing tests first, the points mentioned in this post earlier (writing good quality tests, writing testable code) is all taken care by itself.

A good resource on how the cycle should go –

The 4-contact points of software development

Written by Vishwanath Krishnamurthi

October 23, 2010 at 10:32 pm

Posted in Design