Open GoogleCodeExporter opened 8 years ago
Sounds like a useful feature. I think the expected count could also be given
as a
matcher. For example:
assertThat(list, hasCountOfElements(greaterThan(2), not(equalTo(0))));
Original comment by nat.pr...@gmail.com
on 24 Oct 2008 at 8:51
[deleted comment]
[deleted comment]
Original comment by nat.pr...@gmail.com
on 24 Oct 2008 at 12:34
I think the semantics of a call like
hasCountOfElements(greaterThan(2), not(equalTo(0)))
can be a bit confusing.
It could be interpreted as
the count of elements that have a value greater than 2 is not equal to 0
or it could be interpreted as
the count of elements is greater than 2 for elements with a value not equal to 0.
I think it reads better with
hasAtLeast(1).elements(greaterThan(2))
or
hasAtLeast(3).elements(not(equalTo(0))
But this is purely academic. It would be easy enough to provide several
variants of
factory methods to suit different needs. I'm attaching an example
implementation.
Original comment by patrik.h...@gmail.com
on 24 Oct 2008 at 2:55
Attachments:
The issue with chained methods is that they only work when later clauses are
optional.
What would hasAtLeast(1) mean?
Original comment by nat.pr...@gmail.com
on 24 Oct 2008 at 3:16
After having thought more of this I think it would be more flexible to add
a few factory methods to the org.hamcrest.number.OrderingComparisons class.
These could then be used to build more expressive statements.
exactly(T value)
atLeast(T value)
atMost(T value)
between(T min, T max)
Also I think the naming 'has' was a poor choice. Don't you think 'contains' is
far better since it better reveals the intention of the interface? So I would
like
to see (perhaps a modification to org.hamcrest.core.IsCollectionContaining
class?)
an interface I can use like this, where I can specify the number of elements to
match:
final Collection<Integer> integers = Arrays.asList(3, 6, 4, 2, 3, 7, 1, 9);
assertThat(integers, contains(between(4, 9)).elements()); // Just count the
elements
assertThat(integers, contains(atLeast(2)).elements(equalTo(3))); // Count matching
elements
final Collection<Number> numbers = Arrays.<Number>asList(4, 3.2, null, 0, 7.9);
assertThat(numbers, contains(exactly(1)).elements(nullValue())); // Generics to
allow mixing of types
assertThat(numbers, contains(atLeast(2)).elements(instanceOf(Double.class)));
I am not sure I understand why the later clauses need to be optional?
Meaning the first call need to be a matcher in itself? I would consider the
first call returning a factory for matchers, rather than a matcher in itself,
and would be satisfied with that. Am I missing something?
Original comment by patrik.h...@gmail.com
on 16 Nov 2008 at 6:26
Any chance of any of this being implemented?
Original comment by baker.st...@gmail.com
on 22 Jun 2010 at 10:47
I just posted a similar discussion to the developers mailing list with respect
to counting nodes matching an XPath in a DOM. Mapping what I had done before
switching to Hamcrest to Java, I provided these matchers:
assertThat(dom,
hasXPath('book/title')
.withContent(stringContaining('JUnit'))
.withCount(atLeast(5)));
hasXPath() returns a Matcher and thus withContent() and withCount() are each
optional factories that return Matcher compositions. It was tricky to get the
logic to work so you could use both or either one.
The main problem I see with this design is that each type of object (array,
collection, iterable, query result, etc) needs to implement these factory
methods. Would it instead be possible to create a generic set of factory
methods that could be applied to those Matchers that implement extra
interface(s)?
What about introducing new aggregators that operate on the actual value and
return a value that gets passed to the matcher?
assertThat(dom,
withXPath('book/title'),
withContent(stringContaining('JUnit')),
countItems(),
atLeast(5));
or maybe
assertThat(
count(dom,
withXPath('book/title'),
withContent(stringContaining('JUnit'))
),
atLeast(5));
Ah, the Wiki lists hamcrest-collections that implements select(), reject(),
map(), reduce(), et al:
http://code.google.com/p/hamcrest-collections/wiki/GettingStarted
assertThat(
select(dom,
withXPath('book/title'),
withContent(stringContaining('JUnit')) // not exactly
).size(),
atLeast(5));
It's still missing the concept of composing multiple matchers into a chain that
produces the final list of values to be counted, so above hasXPath() and
withContent() would need to be merged into a single matcher somehow.
For example the above is not and(withXPath(), withContent()). It could be, but
better would be to have withXPath() limit the list and *then* for withContent()
to limit that new list. Of course that's only necessary because of the XPath
library I'm using.
Original comment by dharkn...@gmail.com
on 27 Jul 2010 at 10:18
tagging
Original comment by t.denley
on 12 May 2012 at 11:02
Original issue reported on code.google.com by
patrik.h...@gmail.com
on 23 Oct 2008 at 9:37Attachments: