Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Announcing aUnit, a new unit testing tool for aspects

(Apologies for  the earlier, incomplete email. This followon will skip the
joke.)

> However, I don't think the proposed approach would address all the
> problems in writing pointcuts: because the test description is close to
> the pointcut definition, it's easy to make consistent mistakes, e.g.,
> writing "call(void Account.doFoo()) && within(org.xyz.abc)" when you want
> to match a call to void Account.doFoo(int)). 

I think what's needed is a means of specifying a *concrete* join point (no
wild cards). This avoids  the consistent mistake problem:
somePreviousJoinPoint = //...;
joinPoint = new Call().to(Account.class, "doFoo")
            .with(int(55)).from(Facade.class).under(somePreviousJoinPoint)
            .will(returnValue("Foo done!");

alternately:
mockAccount = new MockAccount(/*whatever*/);
joinPoint = new Call().to(mockAccount, "doFoo")
            .with(int(55)).from(Facade.class).under(somePreviousJoinPoint)
            .will(returnValue("Foo done!");


This second form would allow pointcuts to extract target context from the
"call".

> It seems to me that it would be better to have a compact form for
> describing a concrete join point that looks more like Java code. I wonder
> if it wouldn't be better to use a scripting language instead (like Bean
> Shell or Groovy), e.g., "package x.y.z; class Account { void doFoo() {}
> }"
> 

Oh, er, it looks like Ron's ahead of me. Well, except my proposal is
realizable in Java (it's based off of the JMock API).

> The other approach I can see would be to reflectively examine each piece
> of advice in the aspect (e.g., looking up the associated pointcut's
> description from class attributes) and then to write code that tests each
> against the given string. A benefit of this latter approach would be that
> you could potentially determine whether the test string always matches,
> never matches, sometimes matches, or matches in certain cases depending
> on the runtime state.
>

I'm a little confused as to what you mean by this idea, but it sounds
intriguing.

> Virtual Mock frameworks
> typically provide means to specify simulated behavior, including
> simulated return results (which would be important for testing advice
> too), and allow instrumenting objects under test to determine what
> methods and arguments were called or executed (just as this code snippet
> suggests is needed in assertInvoked).

Yes, this would last would be very important.

Cheers,
Nick
--- Ron Bodkin <rbodkin@xxxxxxxxxxxxxx> wrote:

> This is an interesting proposal that would definitely help. I see it as a
> kind of virtual mocking; today one can unit test abstract aspects by
> using an abstract pointcut for scope and writing a concrete test aspect
> that applies to a dummy object that generates the needed join points.
> I.e., the dummy object is a mock, that's testing the interface with the
> aspect (generating the needed join points).
> 
> However, I don't think the proposed approach would address all the
> problems in writing pointcuts: because the test description is close to
> the pointcut definition, it's easy to make consistent mistakes, e.g.,
> writing "call(void Account.doFoo()) && within(org.xyz.abc)" when you want
> to match a call to void Account.doFoo(int)). 
> 
> I also wonder about the string for tested pointcuts. It seems to me that
> there are a whole range of possible values that couldn't be tested, e.g.,
> what if I put as my test jp string "call(* *(..))"? How about "call(void
> Runnable.run())" or "within(org..*)"? Or "cflow(baz())" or "if(foo)"? How
> about if the pointcut being advised has runtime checks (cflow or if)? 
> 
> It seems to me that it would be better to have a compact form for
> describing a concrete join point that looks more like Java code. I wonder
> if it wouldn't be better to use a scripting language instead (like Bean
> Shell or Groovy), e.g., "package x.y.z; class Account { void doFoo() {}
> }"
> 
> How were you thinking about implementing playBack?  I could imagine using
> dynamic code generation (e.g., with CGLIB), and then weaving the
> resulting bytecode with the given aspect. The tricky part here would be
> generating code that matches the specified join point.
> 
> The other approach I can see would be to reflectively examine each piece
> of advice in the aspect (e.g., looking up the associated pointcut's
> description from class attributes) and then to write code that tests each
> against the given string. A benefit of this latter approach would be that
> you could potentially determine whether the test string always matches,
> never matches, sometimes matches, or matches in certain cases depending
> on the runtime state.
> 
> I also think the design for a tool like this should be integrated with a
> similar API style as virtual mocks for objects (e.g., VirtualMock.org and
> the virtual mock framework in aTrack's library). Virtual Mock frameworks
> typically provide means to specify simulated behavior, including
> simulated return results (which would be important for testing advice
> too), and allow instrumenting objects under test to determine what
> methods and arguments were called or executed (just as this code snippet
> suggests is needed in assertInvoked).
> 
> There's another little fly in the ointment here: because advice is not
> named, it's hard to test for a specific piece of advice being invoked.
> There is a trick available for naming advice: you can use an inner aspect
> with just one piece of advice to name the advice. When AspectJ supports
> Java 5.0, hopefully we will be able to annotate advice to give it a name.
> By the way, are you planning to allow annotations on advice and aspects
> in the first version of AspectJ with Java 5.0 support?
> 
> The test snippet you posted also reminded me of the previous thread "How
> to provide external pcd definition" in which you suggested a reflective
> API with an API like this:
> 
> Pointcut pcd = AspectJElementFactory.createPointcut(
>   "call(void Account.doFoo()) && within(org.xyz.abc)");
> 
> Did you build any of this as part of integrating with Spring?
> 
> Ron
> 
> Ron Bodkin
> Chief Technology Officer
> New Aspects of Software
> o: (415) 824-4690
> m: (415) 509-2895
> 
> 
> > ------------Original Message------------
> > From: Adrian Colyer <adrian_colyer@xxxxxxxxxx>
> > To: aspectj-users@xxxxxxxxxxx
> > Date: Mon, Nov-8-2004 8:52 AM
> > Subject: [aspectj-users] Announcing aUnit, a new unit testing tool for
> aspects
> >
> > How do you unit test aspects in isolation, in the same way that we 
> > might 
> > unit test a class?
> > 
> > Current unit-testing approaches for aspects are lacking in the 
> > following 
> > ways:
> > 
> > * you cannot easily unit test an individual aspect in isolation from 
> > the 
> > rest of the program
> > * you cannot easily test whether the pointcut expression associated 
> > with a 
> > piece of advice matches the join points you expect
> > * you cannot easily test whether the pointcut expression associated 
> > with a 
> > piece of advice matches unwanted join points
> > * you cannot easily test the body of advice in isolation from the rest 
> > of 
> > the program
> > 
> > For example, given the following simple aspect:
> > 
> > public aspect X {
> > 
> >   pointcut anInterestingCall() : call(* Account+.do*(..)) && 
> > within(org.xzy..*);
> > 
> >   before() : anInterestingCall() { ... }
> > 
> > }
> > 
> > We would like to write unit tests that verify:
> > * the pointcut matches a call to Account.doFoo() from within 
> > org.xyz.abc
> > * the pointcut matches a call to SubAccount.doGoo(int x) from within 
> > org.xyz.abc.def
> > * the pointcut does not match a call to Account.doFoo() from within 
> > org.qpr
> > * after matching at a join point, the post-conditions of the advice 
> > body 
> > are established
> > * and so on...
> > 
> > and we want to write these tests without necessarily having to create a
> 
> > 
> > package "org.qpr" and without having to weave and run external classes 
> > (to 
> > the one under test) in order to run the test cases.
> > 
> > Enter aUnit, a seamless extension to JUnit that makes it easy to write 
> > unit tests for aspects. aUnit works by letting the test programmer 
> > specify 
> > a sequence of join points (either programmatically, or parsed from a 
> > string format) that are then "played back" to the aspect. It is then 
> > easy 
> > to test after each join point or set of join points whether the aspect 
> > has 
> > responded as desired. Contextual information at the join points 
> > required 
> > by any advice (such as the objects bound to this or target, or the 
> > values 
> > of arguments) can be supplied by the test case programmer - as either 
> > "real" objects or as mock objects, in accordance with normal unit 
> > testing 
> > conventions. 
> > 
> > Here's an example of a simple aUnit test case:
> > 
> > public void testCallMatching() {
> >    String[] jps = new String[]({"call(void Account.doFoo()) 
> > within(org.xyz.abc)"});
> >    X x = X.aspectOf();
> >    playBack(jps,x);
> >    assertInvoked(x,"before","1");
> >     // ...
> > }
> > 
> > The exact style of the test cases has yet to be finalized, but this 
> > should 
> > give you the idea.
> > 
> > Where can I download a copy of aUnit?
> > 
> > Sadly, you can't. It doesn't exist yet. The idea came to me whilst I 
> > was 
> > out running in the woods this lunchtime. 
> > 
> > BUT, aUnit would make a great project for an MSc and/or for open-source
> 
> > 
> > development. Some of the implementation of aUnit would need to be tied 
> > to 
> > AspectJ implementation details, and we would work with the implementors
> 
> > to 
> > make sure that the necessary interfaces are in place and assistance is 
> > given. When finished, we would like aUnit to be contributed to the 
> > AspectJ 
> > tree under the CPL, to be included as part of the AspectJ distribution.
> 
> > 
> > The project contains some non-trivial challenges (like how to 
> > effectively 
> > test around advice containing calls to proceed) that should make it 
> > very 
> > interesting to work on, and could form a core part of every AspectJ 
> > developers toolkit.
> > 
> > It's something we'd love to work on but just don't have the time to 
> > dedicate to it (hands full with Java 1.5 support). 
> > 
> > So - do you want to build aUnit?  I'd be very interested to hear from 
> > developers or teams keen on taking on this challenge, or indeed from 
> > anyone on the list who has ideas about what aUnit should be like.
> > 
> > -- Adrian
> > Adrian_Colyer@xxxxxxxxxx
> > _______________________________________________
> > aspectj-users mailing list
> 
=== message truncated ===



Back to the top