Re: [Pharo-users] TestAsserter>>assertCollection:hasSameElements:

2015-10-30 Thread jtuc...@objektfabrik.de

Peter,
Adding the feedback generation into makes the API even more 
complicated, because you'd have to ar least pass a String as a fourth 
parameter.

So we'd end up with:


assertExecuting: aBlock with: listOfArguments resultsIn: 
expectedResult otherwise: failureString.


... and if you - like me - wonder if this would be any better than the 
current #assert:description: and some additional bindWith:'s for 
reusable nicer error texts, we may finally agree that we can as well 
leave SUnit as it is ... and bite the bullet of writing a bit more code 
for better feedback.


In this form, I am sure nobody would use it. Or just for very special 
and important tests. So all that I can come up with for now is 
insufficient, unfortunately. Sure, there can be variants that provide 
some standard parameters for most of the arguments, but the base 
problem remains that the API is clumsy.
So my whole point boils down to: please don't add too much cruft to 
SUnit just to get better feedback.


Joachim



Re: [Pharo-users] TestAsserter>>assertCollection:hasSameElements:

2015-10-26 Thread jtuc...@objektfabrik.de

Hi Peter,

I just realize it is probably best to return to your initial post in 
order to not drift into D) ;-)


Am 24.10.15 um 20:36 schrieb Peter Uhnák:

bump? :)

On Tue, Sep 29, 2015 at 12:57 AM, Peter Uhnák > wrote:


How practical it is to do set-based comparison
in TestAsserter>>assertCollection:hasSameElements: ?

For example #(1 1 2) has same elements as #(1 2) which may make
sense for sets, but not for bags.

The main reason I was using it is that in tests the expected
collection may be created by hand,
which means it is very often an array #(...), { ... }, while
models very often return OrderedCollections (at least in my case).

So my question is --- how to compare collections irrespective of
type, and possibly of order?

A) always convert the actual collection toanArray

I don't think it is a good idea to provide tests fro general Collections 
that first convert it to some specialized Collection class. There may be 
nothing wrong with doing so, but it always depends on what exactly you 
want to test for. If converting to an Array is part of that test, the 
test is specialized and not for Collections in general.
Seems to be an indication that your test is not a general Test on 
Collections...



B) change difference: behavior for non-sets (ton of work with
catastrophic consequences)


You name it ;-)


C) extend TAssertable with new methods like

#assertElementsOf: actualCollection equals: expectedCollection
#assertUnorderedElementsOf: actualCollection equals:
expectedCollection

These names (I know, they are just examples, so I don't pick on them 
specifically) are always open for interpretation.



C.a) directly in Pharo/SUnit


No. For several reasons:
* The whole discussione we're having on this
* SUnit is a framework that is cross-platform. You can never be 
completely sure that a certain method on a Collection class which is not 
in the ANSI standard gives you the same results on another Smalltalk



C.b) in independend SUnit-Extensions repository/project

A much better approach. But then we have a portability problem if things 
like extensions and method overrides come into play. So this requires 
architectural changes in SUnit to enable a plugin mechanism. That, btw, 
would be a great thing!



C.c) just in my project

This should surely be a starting point to stabilize things. If we had 
plugins, it would be easy to publish your stuf as plugin at any time.




D) stop discussing non-problems

If you mean others think you should just shut up and you should just do 
it for yourself, then I think it is not a good option. I am quite sure 
your question shows that there is a problem with SUnit. Be it with 
Collections or any other area. SUnit started as something quick and 
dirty and thus is not perfect for many situations. We should look for 
patterns and solutions. I would definitely disagree if you suggest 
people might think your questions are a non-problem!



Joachim

--
---
Objektfabrik Joachim Tuchel  mailto:jtuc...@objektfabrik.de
Fliederweg 1 http://www.objektfabrik.de
D-71640 Ludwigsburg  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0 Fax: +49 7141 56 10 86 1



Re: [Pharo-users] TestAsserter>>assertCollection:hasSameElements:

2015-10-26 Thread Peter Uhnák
On Mon, Oct 26, 2015 at 8:27 AM, jtuc...@objektfabrik.de <
jtuc...@objektfabrik.de> wrote:

> Am 25.10.15 um 16:33 schrieb Peter Uhnák:
>
> > assert:equals:  it's just more typing than #= with no additional outcome
>>
>
> I also disagree, but that may be also because maybe we write tests for
> different purpse.
> If you write tests just to test your code, then whatever... I don't do
> that so I can't comment on that.
>
> However if you do TDD, then tests are to provide feedback, and from that
> perspective you want to see immediately what is the difference. If I see
> that the assertion failed I have to start digging to find out what is the
> difference, which is extra work and bad from feedback perspective. If I
> instead immediately see what I need to see it allows me to faster deduce
> the source of the problem and resolve it.
>
> I'm sorry, but what you are saying doesn't make any sense. Even if I
> "only" want to test code (which is exactly what you do in TDD, btw.), I
> need good feedback.
>

Well, that was a bit of generalization on my part. The point was, that many
people write tests as an afterthought... which means they have different
means of getting feedback from the system (e.g. logging, running manually
the code, etc.). In such situation they often end up testing already mostly
working code, and thus the feedback from the tests is not as important,
because you end up less digging up problems (since large portion were found
and resolved during manual testing).


> We could think about subclassing TestFailure and a way to hand information
> to the TestFailure so that a nice String can be produced. Like a method
> like cull: that adds arguments' printString representation into the failure
> description.
>

You mean #assert:description: ? Because we already have that.


> Please step back for a second and think again: these are two very
> different things. The job of an Assertion is to make a problem visible. The
> representation of the problem is something else, even if these are closely
> related. This is object thinking lesson #2 or so.
>

Object thinking lesson #3 tells me that I should not care about what is
going on behind the curtains. And while I could explicitly separate the
two, if I do it all the time I don't see what's bad about having a
convenience method. (And by looking at Object or String protocol, Pharo is
a lot about having convenience over engineering rigidness).

But: adding more and more misnamed and misleading assertion methods makes
> the use of SUnit frustrating and will make it obsolete over time. If I have
> to hunt for design problems in SUnit because it assumes something to be
> wrong even though my understanding of waht I tested is different, I lose
> way more time than I am ready to accept. This doesn't happen to me often.
> If finding that I misunderstood an assertion method means I lost a few
> hours, the best thing that may happen is that I never use that method
> again. In the worst case, I decide I think SUnit is useless for me. That
> would be really bad, don't you think?
>

I am not sure if we are talking about the same SUnit. Sure, there are 32
methods in the "asserting" protocol, however most of them are either
opposites of one another "#assert: vs #deny:", or they provide some
customization such has "#assert:description:", "#should:raise:" ... so if I
count only meaningfully different methods the number 7 (not to mention that
some of the methods are not even used). But if you have trouble
understanding the purpose of seven methods, then the problem is on your
end, and don't blame SUnit for it.


>
>
>  > assertCollection:hasSameElements:
>
>> > So, let's start by asking what the question really means. Does it mean
>> that one collection is a subset of the other? What about ordering then?
>> Does it mean both contain the same elements at the same position or just
>> the fact that if they both were Sets contained the exact same elements. The
>> question itself is not exact, so how could an answer possibly be?
>>
>
> There is no question about this method, since this is implemented in code
> there is nothing ambiguous. This method effectively converts both arguments
> to sets and compares them like that.
>
>
> Sorry to say that, but this is ambiguity by design: you define
> hasSameElements: as "both result in the same Set". So the name of this
> assertion method is a great example of bad naming, IMO.
>

Yes, the naming is confusing. My point was, that instead of philosophizing
about the meaning you can look at the code. Of course if you use the method
for the first time (like I did), you will get burned by it (as I did).


> The question is whether such thing is useful for non-sets, and there are
> definitely cases where such assertion is not appropriate (when you want to
> ensure that there are specific items or specific positions), that's why I
> suggested asserts specifically for that.
>
> This is just nonsense. You name a method after a general collection 

Re: [Pharo-users] TestAsserter>>assertCollection:hasSameElements:

2015-10-26 Thread jtuc...@objektfabrik.de

Peter,

I see you clearly understand what I wanted to get into and don't give up 
because of my aggressive tone in the first place.


Am 26.10.15 um 23:53 schrieb Peter Uhnák:
On Mon, Oct 26, 2015 at 8:27 AM, jtuc...@objektfabrik.de 
 > wrote:


Am 25.10.15 um 16:33 schrieb Peter Uhnák:


> assert:equals:  it's just more typing than #= with no
additional outcome


I also disagree, but that may be also because maybe we write
tests for different purpse.
If you write tests just to test your code, then whatever... I
don't do that so I can't comment on that.

However if you do TDD, then tests are to provide feedback, and
from that perspective you want to see immediately what is the
difference. If I see that the assertion failed I have to start
digging to find out what is the difference, which is extra work
and bad from feedback perspective. If I instead immediately see
what I need to see it allows me to faster deduce the source of
the problem and resolve it.


I'm sorry, but what you are saying doesn't make any sense. Even if
I "only" want to test code (which is exactly what you do in TDD,
btw.), I need good feedback.


Well, that was a bit of generalization on my part. The point was, that 
many people write tests as an afterthought... which means they have 
different means of getting feedback from the system (e.g. logging, 
running manually the code, etc.). In such situation they often end up 
testing already mostly working code, and thus the feedback from the 
tests is not as important, because you end up less digging up problems 
(since large portion were found and resolved during manual testing).


I don't think there really is a difference between test first and tests 
as an afterthought. You always need good and precise feedback. What you 
say about having learned much more during development of a body of code 
is not necessarily true in teams or when you maintain software that has 
grown for years or decades, Remember, there are Smalltalk systems out 
there whose development started in the late 80s or early 90s. In fact, 
most commercial Smalltalk projects out in the wild are rather old.
If you have to make sure you don't break anything by putting a system 
under test, you need precise feeddback, because errors can happen in 
areas you haven't touched in the last 5 or 10 years or even never before.


There is, btw, another area in which SUnit can be extremely helpful: 
Understanding an existing body of code and proving your theories about 
code to yourself while you dive deeper. Here, feedback is also very 
important.


So let's just assume that feedback of SUnit can never be too specific 
and is one of the very most important aspects of the framework.



We could think about subclassing TestFailure and a way to hand
information to the TestFailure so that a nice String can be
produced. Like a method like cull: that adds arguments'
printString representation into the failure description.


You mean #assert:description: ? Because we already have that.
Well, I actually mean a new generation of #assert:description: that 
concentrates more on the #description: part. Remember: some assertion 
methods have been added as a way to provide "more suitable" feedback, 
like handing in an object or two to be mentioned in the description 
string. So the problem at hand wasn't that the standard assert: method 
was insufficient, just its output.
I clearly understand how this can happen. You want to provide a better 
log output and since you are testing something that even others might 
need, you just add that damn method that writes a nice "expecte $A but 
got $B".
In fact, this solves a problem in the wrong way, because it will result 
in many more or less well-named assertion methods that basically are 
there to provide a better failure String.


So what we have is a way to display a description without parameters. 
But we sometimes want more than that. In case of #assert:equals: we 
wanted a String that says "Expected $A and got $B". Let's not speculate 
whether this String really saves us much time if we are in a TDD 
scenario or on a build server. Let's just assume it is never bad to know 
as much as possible about a problem to do something about it.


Let's also not forget that Kent Beck had this clear idea from the very 
beginning of SUnit that it must be lightweight and easy to understand to 
not shy people away from trying. You must be able to use SUnit within an 
hour and it must be easy and provide instant feedback. If I have to type 
too much, or keep too many things in mind, I won't use it.




Please step back for a second and think again: these are two very
different things. The job of an Assertion is to make a problem
visible. The representation of the problem is something else, even
if these are closely