SUnit: Skipping tests?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
45 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: SUnit: Skipping tests?

Markus Gälli-3

On Mar 29, 2006, at 7:35 PM, Markus Gaelli wrote:

> On the other hand some philosophers like Wittgenstein or linguists  
> like Lakoff would say that there are better and worse examples for  
> a given concept - you would not explain the concept of a bird to a  
> child with a penguin first...
>
> So how do I make explicit which "animal" I am really interested in  
> a test?
>
> Again, just use the block concept.
>
> FooTest >> testBar
> "Our tool is actually able to detect that this is an InverseTest"
>
> "..someSetupCode for blaBla."
> (...)
> self test: [aResult := blaBla bar inverseBar] "All methods called  
> in the test block are methods under test"
>
> "some assertions to make this a test and not a mere example"
> self assert: (aResult = blaBla)

Having said all this, I have to retract my arguments vs.
        self shouldnt:[bb copyBits] raise: Error.
from my morning mail of course...

If its always Error that I don't expect in my methods under test I  
could rewrite

> self test: [aResult := blaBla bar inverseBar] "All methods called  
> in the test block are methods under test"

from above easily into

        self shouldntRaiseError: [aResult := blaBla bar inverseBar] "All  
methods called in the test block are methods under test"
;-)
The only difference to Andreas' solution would be that I would  
bracket the methods under test like this, even if there are some  
assertions down below in the code.

Cheers,

Markus


Reply | Threaded
Open this post in threaded view
|

Re: SUnit: Skipping tests?

Hernan Wilkinson
In reply to this post by Lukas Renggli
--- In [hidden email], "Lukas Renggli" <renggli@...> wrote:

>
> > I think that Diego is saying that it is better not to test the
> > implementation but the behavior of an object. If the implementation
> > changes and you have implementation tests, you will have to change
> > them. On the other hand, if you only test behavior and you change the
> > implementation you should not change the tests.
>
> But this is the same, if you change the behavior or interface, you
> have to adapt the tests as well, so this does not count ;-)
>

Ha, ha, this is a good one... but only if you take it out of context...
Of course that if B depends on A an A changes, then B will have to
change, that is not the issue. I think the issue here is: "What's more
important, implementation or behavior?" and I beleive the answer is
behavior. Implementation can change many times but the
responsibilities of an object, its essence, should change less that
its implementation... (I'm not saying that is always like this, but
that's the idea...)
If I have tests based on behavior, then I can reuse them for different
implementations, for example, a Stack could be implemented with a
List, with an Array, etc., there could even be the two
implementations, but I could use the same tests...
Anyway, having said this, I guess I can answers your "so this does not
count ;-)" with a "so this does not count ;-)" ;-) (hey, just kidding,
don't get mad!).

> > I understand that you would want to see that your implementation is
> > right, but is not enough to test the behavior? what implementation
> > mistake couldn't you find testing the behavior?
>
> You are probably right for most cases.
>
> How do you test class invariants in your test-cases, without exposing
> the internal state of the object?

Well, I beleive that an object's invariant is based on its behavior,
not its implementation. For example, in a CircularList the last and
first elements are linked (if there are elements of course). That's
the invariant no matter if the CircularList uses a DoubleLinkedList,
an OrderedCollection or whatever structure you want to use to
implement the circular list.
I don't think you have to expose the internal state of an object to
test its invariant... The idea of invariant, as I understand it, it is
tied to the concept itself and if you want to test the invariant, that
should happend all the time something changes in the instance of that
concept. That's what Eiffel does, but in Eiffel you write the
invariant as part of the class not as a separate test.

[snip]

> > We have talked with Diego many times about annotations and our opinion
> > is that annotations are a tool that do not follow the idea of having
> > only "objects and messages". It is sintax sugar that makes the
> > language more difficult to use. It is a matter of taste and I don't
> > like sugar :-)... (For sure you have discuss this on the list many
> > times...)
>
> - An annotation is an object, as everything is.
>
> - An annotation is a message(-send), you can send it to any object and
> have behavior and/or a return objects as an effect.

I have to admit that I have not read about annotations, just saw a few
examples, but I'd like you to think about this:
1) When I see an annotation I don't see an object, neither a message
not a message send, I just see "<anAnnotation>".
2) This means that I need to learn something new that is not about
objects and messages (at least explicitly) but about sintax.
This may be a good price to pay, but only if this new tool gives me
something it is hard to do in other ways.

When I see an annotation I see a "tag" (an this is personal, maybe if
I read more about them I'll see other things), wich remembers me and
transports me to the "relational paradigm", where everytime you need
to "tag" something you just create a new "field" on the "row".
But, what is the essence of doing this?, the essence is to create a
categorization. In the case of annotations, to categorize a method
using different "tags".
Well, I beleive categorization can be achieved in a much simple and
flexible way using sets (I mean set in the abstract way) which in the
"relational paradigm" would mean to create a new table, and in the
case of tests using SUnit, to create different suites.
Forgive my ignorance, but how would you categorize a test of beeing,
let's say, an architecture test and an integration test with
annotations? I want to be able to run only architecture tests, or
integration tests, or both or neither.
I cant think of two ways of anotating:
1)
aClass>>test1
   <architectureTest>
   <integrationTest>
   ... the test

2)
aClass>>test1
   <architectureTest>
   <integrationTest>
   <architectureTestAndIntegrationTest>
   ... the test

But I don't kwnow how to obtain which ones are architecture tests,
etc.
Using sets and suites, it is simple:

Set architectureTests := Set with: aClass>>test1 with: ...
Set integrationTests := Set with: aClass>>test1 with: ...
Set archtectureAndIntegrationTests := architectureTests union:
integrationTests.

architectureTestSuite := (TestSuite named:..) addTests: architectureTests.
integrationTestSuite := (TestSuite named:..) addTests: integrationTests.
etc.

If I need to change the categorization, I change the objects (the
sets), not a method, and the info about the categories is in one
place, not spread all over.

Bye,
Hernan.





Reply | Threaded
Open this post in threaded view
|

Re: SUnit: Skipping tests?

Lukas Renggli
> I cant think of two ways of anotating:
> 1)
> aClass>>test1
>    <architectureTest>
>    <integrationTest>
>    ... the test
>
> 2)
> aClass>>test1
>    <architectureTest>
>    <integrationTest>
>    <architectureTestAndIntegrationTest>
>    ... the test
> > But I don't kwnow how to obtain which ones are architecture tests,
> etc.
> Using sets and suites, it is simple:
>
> Set architectureTests := Set with: aClass>>test1 with: ...
> Set integrationTests := Set with: aClass>>test1 with: ...
> Set archtectureAndIntegrationTests := architectureTests union:
> integrationTests.
>
> architectureTestSuite := (TestSuite named:..) addTests: architectureTests.
> integrationTestSuite := (TestSuite named:..) addTests: integrationTests.
> etc.
>
> If I need to change the categorization, I change the objects (the
> sets), not a method, and the info about the categories is in one
> place, not spread all over.

Mhh, I see that different ... ;-)

The problem with your approach is that you categorize your methods at
a different places than you define them. Basically this means I have
to accept two methods, if I add, change or remove a test.

I do very much prefer your annotation example (1) where I directly tag
the concerning method with the necessary meta-information. For me this
is much easier to maintain, because I can see immediately when
browsing the method to what category it belongs to. Moreover I can
quickly query all the currently taged methods by browsing the senders
of #architectureTest. Then I get the suite with one line of code, not
a method full of selectors defined somewhere throughout the image:

Set architectureTests := MethodAnnotation allNamed: #architectureTest
from: aClass.

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

Reply | Threaded
Open this post in threaded view
|

Re: SUnit: Skipping tests?

Hernan Wilkinson
Lukas Renggli wrote:

>Mhh, I see that different ... ;-)
>
>The problem with your approach is that you categorize your methods at
>a different places than you define them. Basically this means I have
>to accept two methods, if I add, change or remove a test.
>
>I do very much prefer your annotation example (1) where I directly tag
>the concerning method with the necessary meta-information. For me this
>is much easier to maintain, because I can see immediately when
>browsing the method to what category it belongs to. Moreover I can
>quickly query all the currently taged methods by browsing the senders
>of #architectureTest. Then I get the suite with one line of code, not
>a method full of selectors defined somewhere throughout the image:
>
>Set architectureTests := MethodAnnotation allNamed: #architectureTest
>from: aClass.
>  
>

I have to agree on that, it is much easier the way you propose...

>Cheers,
>Lukas
>
>--
>Lukas Renggli
>http://www.lukas-renggli.ch
>
>
>
>  
>


--
______________________________
Lic. Hernán A. Wilkinson
Gerente de Desarrollo y Tecnología
Mercap S.R.L.
Tacuari 202 - 7mo Piso - Tel: 54-11-4878-1118
Buenos Aires - Argentina
http://www.mercapsoftware.com
---------------------------------------------------------------------
Este mensaje es confidencial. Puede contener informacion amparada
por el secreto profesional. Si usted ha recibido este e-mail por error,
por favor comuniquenoslo inmediatamente via e-mail y tenga la
amabilidad de eliminarlo de su sistema; no debera copiar el mensaje
ni divulgar su contenido a ninguna persona. Muchas gracias.
 
This message is confidential. It may also contain information that is
privileged or otherwise legally exempt from disclosure. If you have
received it by mistake please let us know by e-mail immediately and
delete it from your system; you should also not copy the message nor
disclose its contents to anyone. Thanks.
 ---------------------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: SUnit: Skipping tests?

Lukas Renggli
> I have to agree on that, it is much easier the way you propose...

Gosh, really? I didn't yet brought up the best argument ... ;-)

Imagine several packages with tests being categorized as
#architectureTests and #integrationTests. Now not all the developers
want to always load all the packages (e.g. maybe packages provide
extensions you don't need in your particular image, or there are extra
packages of other people not under your control). Defining a global
method returning all the #architecutreTests simply doesn't work with
such a setup, querying meta information of methods however does. This
is exactly the problem I was confronted with when developing
Magritte/Pier, and this is the reason why I implemented and itroduced
MethodAnnotations for Squeak 3.9.

Thanks for the interesting discussion!

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch

123