Update - commenters pointed out an obvious mistake - I should have kept the sample code here the same as my real code. I've updated the code samples. Some time ago I asked why unit tests use assertions instead of returning a boolean. I didn't get any particularly convincing answers, so I continued returning a boolean, in my home-grown test framework, that's so small it hardly deserves the name 'framework'. One obvious benefit from using exceptions is that you get the name of the test method and class in the exception output. In my framework, I had to explicitly supply that. Each test object had a getName(). return "TestUninstallingDrivers". Ok, now I have duplication:
public static final UnitTest testUninstallingDrivers=
new UnitTest()
{
public boolean test()
{
stuff..
return !card.hasDrivers();
}
public String getName()
{
return "testUninstallingDrivers";
}
};
The usual "Java programmer" approach would be to just go back to exceptions, then you'd be able to get your IDE to show you the test method by clicking on the stack trace. However, there were some reasons not to go back to exceptions. I'd instead like to generate the getName() implementation based on the field name. I believe at least 2 out of the 3 major IDEs can help me with some kind of template like this:
public static final UnitTest $x=new UnitTest()
{
public boolean test()
{
//Auto-generated method stub. To stop this
//annoying message, go through some dialogs
//that you never really wanted to anyway.
return false;
}
public String getName()
{
return "$x";
}
}
So, that's all well and good, until I start refactoring, because the IDEs do not carry on linking the two expansions of $x even after the template has been applied. When I first heard someone rave about IDEA's Live Templates, I assumed they would provide such linking - they do not.
Plus, even if they did, you'd still see the generated code, which isn't really that useful. The only part of the above code that's relevant to me is the name of the class and the code inside test. That is, I'd be happy with:
unitTest(testUninstallingDrivers,
{
stuff..;
return !card.hasDrivers();
})
..which would generate the above usual Java code. Of course, should I want to see the expanded template, I could just right-click on the template name or something.
So what I'd really like from IDEA's Live Templates is for the template's name to stay in my source code, and to be expanded for compilation. But then, if it's staying in my source code, I can't compile without IDEA, or even with IDEA on another computer (unless I successfully manage my project settings). It would be better if the template could stay in my source code too. The source for the template. E.g.:
template unitTest(name,body)
{
public static final UnitTest <name>=new UnitTest()
{
public boolean test()
{
<body>
}
public String getName()
{
return "<name>";
}
}
};
This would need a preprocessor before the usual Java compiler. There are some difficulties, like the <body> expansion above generating two sets of braces, but they can be resolved (a syntax like <@body> to splice in the body).
In case there's anyone out there who hasn't recognised this yet, I'm really talking about Lisp macros, and not even a significantly complex application of them. I don't see any reason why modern programmers don't use a decent macro system, pretending to be happy with 'Live' Templates, and refactoring everything at a higher level (such as changing the unit test framework to use exceptions) instead of working with the actual source code they like.
For a Lispy implementation of a unit test framework (in 26 lines of Lisp!), see this chapter from Practical Common Lisp.