Support for fest-assert assertions as proxy based condition

58 views
Skip to first unread message

Marcin Zajączkowski

unread,
May 30, 2012, 9:38:17 AM5/30/12
to await...@googlegroups.com
Hi,

I created a feature request to add a support for fest-assert assertions
as proxy based condition:
https://code.google.com/p/awaitility/issues/detail?id=17

I took a look into code and my conclusion is that fest-assert's more
type safe fluent API makes it harder to integrate with Awaitility than
Hamcrest. I did a little bit of hacking (added a new Condition
implementation in ConditionFactory) and generally was able to use
Awaitility with mutable objects:
await().untilCall(to(assertThat(newEmployees)).contains(frodo, sam));

In Awaitility I like very much an ability to retake an immutable object
in every try. In my implementation following will not work:
await().untilCall(to(assertThat(fakeRepository.getValue())).isEqualTo(5));

It would be necessary to use two proxies, one to retake a value to
assert, the second to recall the whole assertion. I played with that
idea, but the result is very messy and I had a problem when a retaking
of a value should be triggered.

Maybe you have a better idea how could it be achieved?

Regards
Marcin

--
http://blog.solidsoft.info/ - Working code is not enough

Johan Haleby

unread,
May 31, 2012, 2:47:37 AM5/31/12
to await...@googlegroups.com
Hi, 

I prefer to use fest-assert as well but it's not as flexible as Hamcrest when it comes to using it in a third-party framework. But how do you "retake" the value from fest-assert in your second example? Perhaps something like this could work:

await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);

I.e. untillCall returns the outcome of "assertThat(fakeRepository.getValue())" (assertThat is called implicitly under the hood by awaitility). 

Regards,
/Johan

Marcin Zajączkowski

unread,
Jun 2, 2012, 7:57:20 AM6/2/12
to await...@googlegroups.com
On 2012-05-31 08:47, Johan Haleby wrote:
> Hi,
>
> I prefer to use fest-assert as well but it's not as flexible as Hamcrest
> when it comes to using it in a third-party framework. But how do you
> "retake" the value from fest-assert in your second example? Perhaps
> something like this could work:
>
> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>
> I.e. untillCall returns the outcome of
> "assertThat(fakeRepository.getValue())" (assertThat is called implicitly
> under the hood by awaitility).

Thanks for a tip. I make a try to implement it, but unfortunately there
is a problem. I can "retake" value using proxy and apply it to
assertThat inside untilCall, but later I have to return value (the
result of assertThat(...)) to execute assertions (here isEqualTo()) and
I don't have control over it (I can't catch exception throws by
isEqualTo() and retry leter).
Maybe you have some clever idea how to achieve it?

Regards
Marcin

Johan Haleby

unread,
Jun 4, 2012, 2:38:56 AM6/4/12
to await...@googlegroups.com
I'm not really sure what you mean but I suppose that what we would have to do is not returning the result of fest-assert's "assertThat(..)" but rather our own implementation of their assertion interfaces (NumberAssert, LongAssert etc) that let us "capture" the values passed in the methods defined in the interfaces such as "isEqualTo". Hamcrest has a way of getting true or false back if a matcher matches a given value (using the "matches" method on a Hamcrest matcher instance). I'm not sure if something similar exists in fest-assert but if it don't I suppose catching the exception from fest-assert would be the only (albeit ugly) way to check if the condition is satisfied. 

Regards,
/Johan

On Sat, Jun 2, 2012 at 1:57 PM, Marcin Zajączkowski <msz...@wp.pl> wrote:
On 2012-05-31 08:47, Johan Haleby wrote:
> Hi,
>
> I prefer to use fest-assert as well but it's not as flexible as Hamcrest
> when it comes to using it in a third-party framework. But how do you
> "retake" the value from fest-assert in your second example? Perhaps
> something like this could work:
>
> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>
> I.e. untillCall returns the outcome of
> "assertThat(fakeRepository.getValue())" (assertThat is called implicitly
> under the hood by awaitility).

Thanks for a tip. I make a try to implement it, but unfortunately there
is a problem. I can "retake" value using proxy and apply it to
assertThat inside untilCall, but later I have to return value (the
result of assertThat(...)) to execute assertions (here isEqualTo()) and
I don't  have control over it (I can't catch exception throws by
isEqualTo() and retry leter).
Maybe you have some clever idea how to achieve it?

Regards
Marcin

Marcin Zajączkowski

unread,
Jun 10, 2012, 12:28:52 PM6/10/12
to await...@googlegroups.com
On 2012-06-04 08:38, Johan Haleby wrote:
> I'm not really sure what you mean but I suppose that what we would have to
> do is not returning the result of fest-assert's "assertThat(..)" but rather
> our own implementation of their assertion interfaces (NumberAssert,
> LongAssert etc) that let us "capture" the values passed in the methods
> defined in the interfaces such as "isEqualTo". Hamcrest has a way of
> getting true or false back if a matcher matches a given value (using the
> "matches" method on a Hamcrest matcher instance). I'm not sure if something
> similar exists in fest-assert but if it don't I suppose catching the
> exception from fest-assert would be the only (albeit ugly) way to check if
> the condition is satisfied.

Hello again. Having some luck I was able to write version for
IntegerAssert which works. I had some problem to make it typed (generics
in Java are so limited...) and at the end had to modified it internally.

Currently there are 4 Callable construction used:
- one in to() to cover argument "retaking"
- one to get newly created in every iteration *Assert instance (a type
is not known during execution - generics are used - I had to create that
Callable when a type is still known) - *AssertThatSupplier
- one in a proxy object for *Assert class
- one used internally by awaitility in await() - in FestTypedCondition

It seems it will be needed to have a method for every type supported by
FEST-assert (20+ methods - like in Assertions class in fest-assert) to
keep fluent interface:
public IntegerAssert untilCall(Integer ignored) throws Exception {
and unfortunately also a small class in each case to get *Assert
instance (see *AssertThatSupplier).

Omitting problem with boilerplate code the biggest problem is with final
methods in fest. Assertions object are classes without corresponding
interfaces and in case of final methods they are silently ignored during
proxing. There are countable number of those methods (e.g. in
AbstractComparableAssert). It could be probably possible to remove all
final modifiers using reflection, but maybe you have some better idea
how to do it (maybe some trick from PowerMock?)?

The code could be optimized, refactored and made cleaner (it is just
PoC). I put it on gist to make you see it and comment. I must admit I
hoped it could be done easier :(.
https://gist.github.com/2906483

Btw, the guys from fest-assert are currently working on version 2.0, so
there is a chance to make some not backward compatible modification in
their code in case you have some cool ideas.

Regards
Marcin


> On Sat, Jun 2, 2012 at 1:57 PM, Marcin Zaj�czkowski <msz...@wp.pl> wrote:
>
>> On 2012-05-31 08:47, Johan Haleby wrote:
>>> Hi,
>>>
>>> I prefer to use fest-assert as well but it's not as flexible as Hamcrest
>>> when it comes to using it in a third-party framework. But how do you
>>> "retake" the value from fest-assert in your second example? Perhaps
>>> something like this could work:
>>>
>>> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>>>
>>> I.e. untillCall returns the outcome of
>>> "assertThat(fakeRepository.getValue())" (assertThat is called implicitly
>>> under the hood by awaitility).
>>
>> Thanks for a tip. I make a try to implement it, but unfortunately there
>> is a problem. I can "retake" value using proxy and apply it to
>> assertThat inside untilCall, but later I have to return value (the
>> result of assertThat(...)) to execute assertions (here isEqualTo()) and
>> I don't have control over it (I can't catch exception throws by
>> isEqualTo() and retry leter).
>> Maybe you have some clever idea how to achieve it?
>>
>> Regards
>> Marcin
>>
>>
>>> On Wed, May 30, 2012 at 3:38 PM, Marcin Zaj�czkowski <msz...@wp.pl>

Johan Haleby

unread,
Jun 11, 2012, 2:20:00 AM6/11/12
to await...@googlegroups.com
Hi, 

Thanks a lot for your interest and work! Do you think it's better to wait for version 2.0 of fest-assert? Do you know if everything would have to be rewritten? Btw, do you have a usage example that demonstrates awaitility and fest-assert?

Also, how should we deal with the integration of fest-assert and awaitility? Perhaps a good idea would be to extract the matcher implementations (Hamcrest and fest-assert) to different modules that depend on "awaitility-core". In this way it would also be possible to write a fest-assert 2.0 module when it arrives. I think this may be a good approach but it'll probably require a lot of work and unfortunately I don't have much of it nowadays :/

Regarding final methods it's not possible to get around that using reflection. You'll need byte-code manipulation and I don't think we want to go down that road..

Regards,
/Johan



> On Sat, Jun 2, 2012 at 1:57 PM, Marcin Zajączkowski <msz...@wp.pl> wrote:
>
>> On 2012-05-31 08:47, Johan Haleby wrote:
>>> Hi,
>>>
>>> I prefer to use fest-assert as well but it's not as flexible as Hamcrest
>>> when it comes to using it in a third-party framework. But how do you
>>> "retake" the value from fest-assert in your second example? Perhaps
>>> something like this could work:
>>>
>>> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>>>
>>> I.e. untillCall returns the outcome of
>>> "assertThat(fakeRepository.getValue())" (assertThat is called implicitly
>>> under the hood by awaitility).
>>
>> Thanks for a tip. I make a try to implement it, but unfortunately there
>> is a problem. I can "retake" value using proxy and apply it to
>> assertThat inside untilCall, but later I have to return value (the
>> result of assertThat(...)) to execute assertions (here isEqualTo()) and
>> I don't  have control over it (I can't catch exception throws by
>> isEqualTo() and retry leter).
>> Maybe you have some clever idea how to achieve it?
>>
>> Regards
>> Marcin
>>
>>
>>> On Wed, May 30, 2012 at 3:38 PM, Marcin Zajączkowski <msz...@wp.pl>

Marcin Zajączkowski

unread,
Jun 11, 2012, 7:04:38 PM6/11/12
to await...@googlegroups.com
On 2012-06-11 08:20, Johan Haleby wrote:
> Hi,
>
> Thanks a lot for your interest and work! Do you think it's better to wait
> for version 2.0 of fest-assert? Do you know if everything would have to be

I planned to implement the idea with assertion with timeout directly
into fest-assert 2.0 [1]. I did some PoC, but later found awaitility
which seems to be suitable for that purpose (the wait..until part is
already implemented). My current PoC for awaitility is based on 2.0
branch (currently on milestone 5) and I will keep it in sync with 2.0.
Probably I would be a good idea to will with release the next version of
awaitility (if any :) ) after 2.0-final, but I see in those changed in
fest-assert a chance (opportunity) to make some incompatible changes to
make it easier to integrate with awaitility. So work should be rather
done in the same time.

[1] - https://jira.codehaus.org/browse/FEST-475

> rewritten? Btw, do you have a usage example that demonstrates awaitility
> and fest-assert?

Yes, I wrote a few unit test to test my PoC. Sample test with integer
value to be put into AwaitilityTest.

@Test
public void shouldAssertWithTimeoutAssertionFromFest() throws Exception {
//given
new Asynch(fakeRepository).perform();

//when

awaitFest().untilCallFest(to(fakeRepository).getValue()).isGreaterThan(0);

//then
assertEquals(1, fakeRepository.getValue());
}

awaitFest (quick and dirty hack to make it testale) is a static method
in Awaitility:
public static FestConditionFactory awaitFest() {
return awaitFest(null);
}

public static FestConditionFactory awaitFest(String alias) {
return new FestConditionFactory(alias, defaultTimeout,
defaultPollInterval, defaultPollDelay,
defaultCatchUncaughtExceptions);
}

> Also, how should we deal with the integration of fest-assert and
> awaitility? Perhaps a good idea would be to extract the matcher
> implementations (Hamcrest and fest-assert) to different modules that depend
> on "awaitility-core". In this way it would also be possible to write a
> fest-assert 2.0 module when it arrives. I think this may be a good approach
> but it'll probably require a lot of work and unfortunately I don't have
> much of it nowadays :/

I was thinking about separate module with support for fest-assert to not
introduce new dependencies for people using only awaitility with
Hamcrest and to allow to optional support both fest-assert 1.4 and 2.0.
The separated core module could be even more useful, but I think in a
first/base version Hamcrest could stay in the base package.

> Regarding final methods it's not possible to get around that using
> reflection. You'll need byte-code manipulation and I don't think we want to
> go down that road..

That's bad. The problem with final methods was also the main problem
with my PoC in pure fest-assert. I hoped to be able to mitigate it
somehow. I will talk with people from fest-assert what do they think
about remove final keywords or if they have some other idea.

Regards
Marcin
>>> On Sat, Jun 2, 2012 at 1:57 PM, Marcin Zaj�czkowski <msz...@wp.pl>
>> wrote:
>>>
>>>> On 2012-05-31 08:47, Johan Haleby wrote:
>>>>> Hi,
>>>>>
>>>>> I prefer to use fest-assert as well but it's not as flexible as
>> Hamcrest
>>>>> when it comes to using it in a third-party framework. But how do you
>>>>> "retake" the value from fest-assert in your second example? Perhaps
>>>>> something like this could work:
>>>>>
>>>>> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>>>>>
>>>>> I.e. untillCall returns the outcome of
>>>>> "assertThat(fakeRepository.getValue())" (assertThat is called
>> implicitly
>>>>> under the hood by awaitility).
>>>>
>>>> Thanks for a tip. I make a try to implement it, but unfortunately there
>>>> is a problem. I can "retake" value using proxy and apply it to
>>>> assertThat inside untilCall, but later I have to return value (the
>>>> result of assertThat(...)) to execute assertions (here isEqualTo()) and
>>>> I don't have control over it (I can't catch exception throws by
>>>> isEqualTo() and retry leter).
>>>> Maybe you have some clever idea how to achieve it?
>>>>
>>>> Regards
>>>> Marcin
>>>>
>>>>
>>>>> On Wed, May 30, 2012 at 3:38 PM, Marcin Zaj�czkowski <msz...@wp.pl>

Johan Haleby

unread,
Jun 12, 2012, 12:42:07 PM6/12/12
to await...@googlegroups.com
Hej,

Oh so you're involved with fest-assert yourself? Then I must give you credit, I use it all the time and I look forward to the next version! :)

I agree that in the first fest-assert version it's probably better to keep Hamcrest as "core" since it will require much less work. 

What's the reason for fest-assert using final methods?

Regards,
/Johan

>>> On Sat, Jun 2, 2012 at 1:57 PM, Marcin Zajączkowski <msz...@wp.pl>

>> wrote:
>>>
>>>> On 2012-05-31 08:47, Johan Haleby wrote:
>>>>> Hi,
>>>>>
>>>>> I prefer to use fest-assert as well but it's not as flexible as
>> Hamcrest
>>>>> when it comes to using it in a third-party framework. But how do you
>>>>> "retake" the value from fest-assert in your second example? Perhaps
>>>>> something like this could work:
>>>>>
>>>>> await().untilCall(to(fakeRepository).getValue()).isEqualTo(5);
>>>>>
>>>>> I.e. untillCall returns the outcome of
>>>>> "assertThat(fakeRepository.getValue())" (assertThat is called
>> implicitly
>>>>> under the hood by awaitility).
>>>>
>>>> Thanks for a tip. I make a try to implement it, but unfortunately there
>>>> is a problem. I can "retake" value using proxy and apply it to
>>>> assertThat inside untilCall, but later I have to return value (the
>>>> result of assertThat(...)) to execute assertions (here isEqualTo()) and
>>>> I don't  have control over it (I can't catch exception throws by
>>>> isEqualTo() and retry leter).
>>>> Maybe you have some clever idea how to achieve it?
>>>>
>>>> Regards
>>>> Marcin
>>>>
>>>>
>>>>> On Wed, May 30, 2012 at 3:38 PM, Marcin Zajączkowski <msz...@wp.pl>

Marcin Zajączkowski

unread,
Jun 12, 2012, 7:00:40 PM6/12/12
to await...@googlegroups.com
On 2012-06-12 18:42, Johan Haleby wrote:
> Hej,
>
> Oh so you're involved with fest-assert yourself? Then I must give you
> credit, I use it all the time and I look forward to the next version! :)

It's an exaggeration :). I'm not a core developer in fest-assert, I'm
rather a guy who like to find and use interesting libraries and tools
and when there is some new feature needed I like to propose a change,
often having fun in providing some (small or larger) patches. That was
with Perf4j, mockito, fest-assert and now is with awaitility :).

> I agree that in the first fest-assert version it's probably better to keep
> Hamcrest as "core" since it will require much less work.

Assuming that problem with final methods will be solved, how would you
see incorporating the fest related changes into the project?
- ConditionFactory - currently I just make a subclass
FestConditionFactory, but maybe it would be useful to make an abstract
super class with the most of the stuff and HamcrestConditionFactory and
FestConditionFactory having only various until* methods with concrete
implementation?
- Awaitility - the most of the stuff will be common, but it is needed
to allow await() methods creating FestConditionFactory to be in a
separate class (and module), those methods are static, so inheritance
won't help much
- some changes in the test classes will be needed to allow testing
different data types returned from the FakeRepository

Probably you see some more places to change.

> What's the reason for fest-assert using final methods?

I'm not sure, but usually it is rather a "hint" to not to try to
override methods (which shouldn't be needed to override) in concrete
assertionts (e.g. AbstractComparableAssert - everything should be
covered by that class when working with Comparable objects).
I asked Joel in the mentioned issue about that. Maybe it won't be a
problem for him to remove those final modifiers. In other case there
could be a problem with fest-assert integration with awaitility :(.

Regards
Marcin

Marcin Zajączkowski

unread,
Jun 16, 2012, 8:23:58 AM6/16/12
to await...@googlegroups.com
On 2012-06-13 01:00, Marcin Zajączkowski wrote:
> On 2012-06-12 18:42, Johan Haleby wrote:
>> Hej,
>>
>> Oh so you're involved with fest-assert yourself? Then I must give you
>> credit, I use it all the time and I look forward to the next version! :)
>
> It's an exaggeration :). I'm not a core developer in fest-assert, I'm
> rather a guy who like to find and use interesting libraries and tools
> and when there is some new feature needed I like to propose a change,
> often having fun in providing some (small or larger) patches. That was
> with Perf4j, mockito, fest-assert and now is with awaitility :).
>
>> I agree that in the first fest-assert version it's probably better to keep
>> Hamcrest as "core" since it will require much less work.
>
> Assuming that problem with final methods will be solved, how would you
> see incorporating the fest related changes into the project?

Joel from fest-assert said that it shouldn't be a problem and will do it
do corresponding changes in the nearest future. I can temporarily remove
them in my local repo, so maybe you thought about integration changes
proposed below?

Marcin

Johan Haleby

unread,
Jun 18, 2012, 2:11:09 AM6/18/12
to await...@googlegroups.com
I haven't looked into it in detail but I think what you're saying sounds good. I imagine that the we would need an awaitility-core module and then one Hamcrest module and one fest-assert module. But I'm also not sure how to hook in the right ConditionFactory implementation and still maintain the fluent interface. I'm not sure if it's even possible... As a last resort I suppose that the entire DSL (await().until(..) etc) would have to be re-implemented for each sub-module (hamcrest/fest-assert). This is of course something we like to avoid but right now I can't come up with a good approach. We need to think about it a little while :)

> What's the reason for fest-assert using final methods?

I'm not sure, but usually it is rather a "hint" to not to try to
override methods (which shouldn't be needed to override) in concrete
assertionts (e.g. AbstractComparableAssert - everything should be
covered by that class when working with Comparable objects).
I asked Joel in the mentioned issue about that. Maybe it won't be a
problem for him to remove those final modifiers. In other case there
could be a problem with fest-assert integration with awaitility :(.

This is a quite common use case for final methods but it may lead to unexpected consequences such as the one we've now discovered.
Reply all
Reply to author
Forward
0 new messages