Author Login
Post Reply
Nat,
thanks for the responses.
> It sounds like you're focusing the test on the wrong thing. I would
> not write a test for each "step" in the process method. Rather I'd
> focus it on each feature of the object as far as the client is
> concerned, running (and testing) the entire process method from entry
> to exit in each test.
When each step is a logical function then this is where the problem is.
My current code looks like this roughly:
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
// For each annotation type to be processed.
for (TypeElement annotation : annotations) {
// For each annotated element.
for (Element element :
roundEnv.getElementsAnnotatedWith(annotation)) {
// If the annotated element is a class.
if (element.getKind().isClass()) {
// Process class element.
processClassElement(element);
}
}
}
// Always a true response
return true;
}
/**
* Process a class element.
*
* @param element Class element.
*/
private void processClassElement(Element element) {
processSource(element);
// If there are class processors.
if (this.classProcessors != null) {
// with each class processor.
for (ElementProcessor elementProcessor : this.classProcessors) {
// ###### JUST ADDED THIS
elementProcessor.setProcessingEnvironment(this.processingEnv);
// Inject the source code reader.
elementProcessor.setSourceCodeReader(this.sourceCodeReader);
// Process this element.
elementProcessor.process(element);
}
}
else {
// Raise compiler warning.
this.processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING, "No class processors found");
}
}
/**
* Processes the source code for a class element.
*
* @param element The class element.
*/
private void processSource(Element element) {
try {
// Try and process any source file attached to the class element.
Source source = this.sourceCodeReader.getSource(element);
this.sourceCodeProcessor.setSource(source);
this.sourceCodeProcessor.process();
}
catch (SourceReaderException e) {
// Raise compiler warning.
this.processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING, "Problem reading source code");
}
catch (SourceProcessorException e) {
// Raise compiler warning.
this.processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING, "Problem processing source
code");
}
}
Now I have tests which assert that each collaborator is invoked as
expected because I need to be
sure that this behaviour is always carried out.
And I have tests to make sure that exceptions thrown at any point are
handled correctly.
Every step above is carried out when the process() method is invoked. This
is part of the Java API
which I have no access to changing so need to accept. A list of mocks is
passed in, which is then
broken down into another list of mocks, which then a bunch of stuff need
to be done with.
So for an example, the test which gets to the end of the process looks like
/**
* Tests that the source code is processed.
*/
@Test(groups = "unit")
public void testSourceIsProcessed()
throws SourceReaderException, SourceProcessorException {
// Set up expectations.
this.mockery.checking(new Expectations() {
{
// Get all annotated elements for this annotation.
allowing(roundEnvironment).getElementsAnnotatedWith(annotation);
will(returnValue(elements));
// The first element is a class.
allowing(element).getKind();
will(returnValue(ElementKind.CLASS));
// Ignore the class processor for this test.
ignoring(classProcessor);
// Expect the source code reader to return source object.
allowing(sourceCodeReader).getSource(element);
will(returnValue(source));
// Ignore.
ignoring(sourceCodeProcessor).setSource(source);
// Process the source.
oneOf(sourceCodeProcessor).process();
}
});
// Process.
this.coreClassElementProcessor.process(this.annotations,
this.roundEnvironment);
}
Where the process() on the source code processor is invoked is my
(current) final step.
So I have now came across a step in one of my collaborators where an
object in the parent
is required so I have added the bit above which says
// ###### JUST ADDED THIS
elementProcessor.setProcessingEnvironment(this.processingEnv);
My main question is, in order to add this one line, every single test now
fails with
"unexpected invocation:
elementProcessor.setProcessingEnvironment(<processingEnvironment>)"
So I then need to add the following to every single failing test.
// Ignore.
ignoring(elementProcessor).setProcessingEnvironmen(processingEnvironment);
So my tests are growing with all these "ignore" expectations, which is
making the tests look
complicated and unreadable. Regardless of what I focus my testing on, I am
still going to need
to ignore everything that happened before it.
And my class is very basic. I dont think this class can be made finer
grained without further
convoluting things.
I hope what I have written makes sense there, my head is spinning a little.
Chris
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email