AspectJ Interactive Testing Script - SDWest 2002
Talk Title: "Better Java Development with AspectJ"
Demo time: 30 minutes
Corresponding sources: aspectj-demo/examples/TestInoculated
To do
- create Testing.lst configuration
- Make pointcut in BufferTest named
To be added
- Show how the "uses pointcut" association reflect the pointcut/advice
referential structure.
Introduction
- Describe AJDE Support and show slides (aspectj-demo/slides/AJDE
Screenshots.ppt)
- Emacs and JDEE
- NetBeans
- AJBrowser
- AJDoc
- Remainder of demo will be in Eclipse and JBuilder support
- Switch to Eclipse
- Run the FigureEditor and describe the sample system.
Show precondition checking (Eclipse)
- Open figures/support/Enforcement.java
- Write before advice that does precondition checking on Points.
before(int newValue): set(int Point.*) &&
args(newValue) {
if (newValue < 0) {
throw new
IllegalArgumentException("too small");
}
}
- Write violation in figures.Main.main(..):
Point p = new Point(-10, 0);
- Run, when error thrown navigate to place of violation and fix violation.
Refactor crosscutting concern into an aspect (Eclipse)
- Open figures/support/Enforcement.java
- Write declare or aspect to find calls to Canvas.updateHistory()
declare warning: !within(Enforcement) && call(void Canvas.updateHistory(..)):
"";
- Navigate all places where it's called
- Write "after returning" advice to capture this functionality
after() returning: call(void FigureElement+.set*(..))
{
Canvas.updateHistory();
}
- Navigate resulting crosscutting structure
- Explain that I had missed putting the update on SlothfulPoint
Show declare error (Eclipse)
- Open figures/support/Enforcement.java
- Want to make sure that sets of private fields of classes implementing
FigureElement only happen from within the set methods
declare error:
set(private * FigureElement+.*) &&
!(withincode(* FigureElement+.set*(..)) ||
withincode(FigureElement+.new(..))):
"should only assign to fields from set methods";
- Compile and navigate places where it is violated
- Fix violations
Recorders for Capturing Input (JBuilder)
- Open "RecordingInput" aspect and select "RecordingInput" configuration.
- Explain the pointcut:
pointcut capacityCall(int i):
within(com.xerox..*) && args(i) &&
call(public int PrinterBuffer.capacity(int)) ;
- Explain the advice:
"Before calling capacity() from within any com.xerox
package, print argument i as input to the XML log."
- Build.
- Explain the inline structure annotations
- Navigate annotations
- Relate them to the structure view.
- Execute and explain output and joinpoint state.
- Explain that this could be useful to take XML output to drive regression
tests.
Using Drivers to Replay Input (JBuilder)
- Open "BufferTest" aspect.
- Switch configuration to "Testing" and explain build configurations.
- Explain the code:
"To drive methods through relevant input values, we can
use around advice. The following aspect works by taking over, whenever a
print buffer's capacity method is called, to drive through the range of
inputs".
- Explain the pointcut:
call(int PrinterBuffer.capacity(int)) && args(original) &&
target(buffer)
- Reset the main class to "BufferTest".
- Build and execute.
- Review the output.
Assembling Tests With Stubs (JBuilder)
- Open "Injection".
- Explain the code:
"We can use advice to change input values, return
different values or throw exceptions at any join point. Let's say we
suspect that our print job is not converting exceptions from the printer
stream. This advice code queries the driver for an exception to throw if
this is an error test. It gets the variable driver as bound by the testEntryPoint pointcut and stream as bound by the testCheckPoint pointcut,
which picks out any public method declared to throw an IOException.
Because this is after returning advice, it runs only where the join point is
not throwing an exception."
- Explain the concept using an interaction diagram slide.
- Reset the main class to "Injection"
- Build and execute.
- Review the output.