TDD and BDD

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

TDD and BDD

demarey
Hi,

With BDD a current test practice is to start method names with 'should'.
It is not yet possible in Pharo but easily do-able (update of TestCase and some Nautilus methods).
I would like that Pharo detects tes methods all methods of a class subclassing (directly or not) TestCase AND starting with either 'test' or 'should'.
I also would like to add 'deny' to not use 'shouldNot' but here I'm not sure.

WDYT?

Christophe.
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sven Van Caekenberghe-2
You could override TestCase class>>#testSelectors in your own subclass, no ?

> On 20 Apr 2015, at 12:02, Christophe Demarey <[hidden email]> wrote:
>
> Hi,
>
> With BDD a current test practice is to start method names with 'should'.
> It is not yet possible in Pharo but easily do-able (update of TestCase and some Nautilus methods).
> I would like that Pharo detects tes methods all methods of a class subclassing (directly or not) TestCase AND starting with either 'test' or 'should'.
> I also would like to add 'deny' to not use 'shouldNot' but here I'm not sure.
>
> WDYT?
>
> Christophe.


Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey
Yes, I could but as it is something that is not specific to a project, I would prefer to have it in the system.

Le 20 avr. 2015 à 12:47, Sven Van Caekenberghe a écrit :

> You could override TestCase class>>#testSelectors in your own subclass, no ?
>
>> On 20 Apr 2015, at 12:02, Christophe Demarey <[hidden email]> wrote:
>>
>> Hi,
>>
>> With BDD a current test practice is to start method names with 'should'.
>> It is not yet possible in Pharo but easily do-able (update of TestCase and some Nautilus methods).
>> I would like that Pharo detects tes methods all methods of a class subclassing (directly or not) TestCase AND starting with either 'test' or 'should'.
>> I also would like to add 'deny' to not use 'shouldNot' but here I'm not sure.
>>
>> WDYT?
>>
>> Christophe.
>
>


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sean P. DeNigris
Administrator
demarey wrote
as it is something that is not specific to a project, I would prefer to have it in the system.
I agree that would be nice. I much prefer #shouldXyz. At the same time I don't mind so much having to override #testSelectors, and if we make this change, we must be ready for people to use it in Core, which IMHO might lead to better tests, but will clash a bit with current style.

BTW if you have to change it in several places, the first step, whether we change the logic or not, would be to refactor so that all those places use one implementation somewhere.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sean P. DeNigris
Administrator
Sean P. DeNigris wrote
refactor so that all those places use one implementation somewhere.
In fact, searching the sources for "beginsWith: 'test'", the logic is duplicated quite a bit. And someone even snuck your proposed change into CompiledMethod>>#isTestMethod, so now we already have two conflicting concepts of what a test selector is in Core.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

stepharo

>> refactor so that all those places use one implementation somewhere.
> In fact, searching the sources for "beginsWith: 'test'", the logic is
> duplicated quite a bit.
So we should refactor it.

> And someone even snuck your proposed change into
> CompiledMethod>>#isTestMethod, so now we already have two conflicting
> concepts of what a test selector is in Core.
>
>
>
> -----
> Cheers,
> Sean
> --
> View this message in context: http://forum.world.st/TDD-and-BDD-tp4820612p4820673.html
> Sent from the Pharo Smalltalk Developers mailing list archive at Nabble.com.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Miguel Moquillon
In reply to this post by demarey
Hi,

BDD and TDD stands for different purposes with different actors.
In BDD, stakeholders work on the functionalities of software units (coarse grain, black-box approach) whereas on TDD developers work on the object's features (fine-grain, white-box approach) that made the functionalities. So, the tooling in BDD should be different of the tooling used in TDD (BDD is more high-level than TDD).

In BDD each functionalities are describes as :

As a <role>
I want <some feature>
So that <I gain a benefit>

And the functionality is described in different scenarios (nominal and error ones) :
Given <some initial context>
When <an event occurs>
Then <ensure some outcomes>

Basic example:

As a customer,
I want to withdraw cash from an ATM,
so that I don’t have to wait in line at the bank.

Scenario 1: Account is in credit
Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned

In fact, a useful and good BDD tool must provide :
  • a way to define a set of initial data
  • a DSL to define the functionalities and for each of them to express the scenarios according to the schema above
  • an engine that feeds automatically the scenario from the data set and that outputs the result.
Miguel Moquillon

Le 20/04/2015 12:02, Christophe Demarey a écrit :
Hi,

With BDD a current test practice is to start method names with 'should'.
It is not yet possible in Pharo but easily do-able (update of TestCase and some Nautilus methods).
I would like that Pharo detects tes methods all methods of a class subclassing (directly or not) TestCase AND starting with either 'test' or 'should'.
I also would like to add 'deny' to not use 'shouldNot' but here I'm not sure.

WDYT?

Christophe.

Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey
In reply to this post by Sean P. DeNigris

Le 20 avr. 2015 à 18:23, Sean P. DeNigris a écrit :

Sean P. DeNigris wrote
refactor so that all those places use one implementation somewhere.

In fact, searching the sources for "beginsWith: 'test'", the logic is
duplicated quite a bit. And someone even snuck your proposed change into
CompiledMethod>>#isTestMethod, so now we already have two conflicting
concepts of what a test selector is in Core.

In fact, I already did the changes in an image (but not published, I wait for feedback) and I also noticed the duplicated logic.

What I did is really simple:
  • In TestCase Class,
    • add 
    • update #testSelectors and #methodChanged: to use #isTestSelector:
    • update shouldInheritSelectors to fix a wrong behavior
  • In ClassTestCase, update selectorsTested to use  #isTestSelector:
  • Update Nautilus extension method CompiledMethod>>isTestMethod to use TestCase>>#isTestSelector:

I will add a slice for that but I'm not sure if it is a good idea to include tests beginning with deny.

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey
In reply to this post by Miguel Moquillon
Hi,

Le 21 avr. 2015 à 10:14, Miguel Moquillon a écrit :

Hi,

BDD and TDD stands for different purposes with different actors.
In BDD, stakeholders work on the functionalities of software units (coarse grain, black-box approach) whereas on TDD developers work on the object's features (fine-grain, white-box approach) that made the functionalities. So, the tooling in BDD should be different of the tooling used in TDD (BDD is more high-level than TDD).

In BDD each functionalities are describes as :

As a <role>
I want <some feature>
So that <I gain a benefit>

And the functionality is described in different scenarios (nominal and error ones) :
Given <some initial context>
When <an event occurs>
Then <ensure some outcomes>

Basic example:

As a customer,
I want to withdraw cash from an ATM,
so that I don’t have to wait in line at the bank.

Scenario 1: Account is in credit
Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned

In fact, a useful and good BDD tool must provide :
  • a way to define a set of initial data
  • a DSL to define the functionalities and for each of them to express the scenarios according to the schema above
  • an engine that feeds automatically the scenario from the data set and that outputs the result.
Miguel Moquillon

yes, you're right on all these points. I'm not aware of such a library for Pharo but it would be very nice. On top of that, you could add a dashboard collecting automatically these tests (that are more or less User Stories) to show your customer which user stories are completed.

To come back to my proposition, it is just a first step to BDD to not prevent people to define tests with something like shouldAccountBalanceBePositiveAfterEachOperation (more behavior driven) rather than testMyWonderfulMethod that may leads people to test the implementation details and not the expected behavior.


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sven Van Caekenberghe-2

> On 21 Apr 2015, at 10:36, Christophe Demarey <[hidden email]> wrote:
>
> To come back to my proposition, it is just a first step to BDD to not prevent people to define tests with something like shouldAccountBalanceBePositiveAfterEachOperation (more behavior driven) rather than testMyWonderfulMethod that may leads people to test the implementation details and not the expected behavior.

Not that your naming ideas are bad, but right now you can write

testAccountShouldBePositiveAfterEachOperation

which is not that bad
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Stephan Eggermont-3
In reply to this post by Miguel Moquillon
On 21/04/15 10:14, Miguel Moquillon wrote:

> In BDD each functionalities are describes as :
>
> As a <role>
> I want <some feature>
> So that <I gain a benefit>
>
> And the functionality is described in different scenarios (nominal and
> error ones) :
> Given <some initial context>
> When <an event occurs>
> Then <ensure some outcomes>

This can be mapped rather easily on a subclass of TestCase, even the
variants with tabled examples. With glamour now in the core, it is
easy to make a specialized browser (and editor) for these tests.
Given and When map to setUp, then to the test. Just add BDDGoal
BDDStakeHolder and BDDFeature and make sure that a BDDTest refers to
them.

Stephan




Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

EstebanLM
In reply to this post by demarey

On 21 Apr 2015, at 10:22, Christophe Demarey <[hidden email]> wrote:


Le 20 avr. 2015 à 18:23, Sean P. DeNigris a écrit :

Sean P. DeNigris wrote
refactor so that all those places use one implementation somewhere.

In fact, searching the sources for "beginsWith: 'test'", the logic is
duplicated quite a bit. And someone even snuck your proposed change into
CompiledMethod>>#isTestMethod, so now we already have two conflicting
concepts of what a test selector is in Core.

In fact, I already did the changes in an image (but not published, I wait for feedback) and I also noticed the duplicated logic.

What I did is really simple:
  • In TestCase Class,
    • add 
<Capture d’écran 2015-04-21 à 10.12.36.png>

hi, side note: 
take into account that the use of #or: as you are using it is not recommended. 
Better something like: 

firstTerm 
or: [ secondTerm 
or: [ thirdTerm 
or [ etc. ] ] ]

yes, is uglier, but faster :)

cheers, 
Esteban

    • update #testSelectors and #methodChanged: to use #isTestSelector:
    • update shouldInheritSelectors to fix a wrong behavior
  • In ClassTestCase, update selectorsTested to use  #isTestSelector:
  • Update Nautilus extension method CompiledMethod>>isTestMethod to use TestCase>>#isTestSelector:

I will add a slice for that but I'm not sure if it is a good idea to include tests beginning with deny.

Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey
In reply to this post by Sven Van Caekenberghe-2

Le 21 avr. 2015 à 10:44, Sven Van Caekenberghe a écrit :


On 21 Apr 2015, at 10:36, Christophe Demarey <[hidden email]> wrote:

To come back to my proposition, it is just a first step to BDD to not prevent people to define tests with something like shouldAccountBalanceBePositiveAfterEachOperation (more behavior driven) rather than testMyWonderfulMethod that may leads people to test the implementation details and not the expected behavior.

Not that your naming ideas are bad, but right now you can write

testAccountShouldBePositiveAfterEachOperation

which is not that bad

I agree. I do not want to push things that won't be used. That's why I did not yet proposed a slice.
Maybe I will just let it as it is now and just propose to include the refactoring to have the logic of the test selection in one place.
With Guille, we discussed a bit around tests and came to the conclusion that it would be good to have a blog post or a book chapter on test solutions and how to test the good thing.
We have, for example:

Thanks for the feedback.

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey
In reply to this post by EstebanLM

Le 21 avr. 2015 à 11:38, Esteban Lorenzano a écrit :


On 21 Apr 2015, at 10:22, Christophe Demarey <[hidden email]> wrote:


Le 20 avr. 2015 à 18:23, Sean P. DeNigris a écrit :

Sean P. DeNigris wrote
refactor so that all those places use one implementation somewhere.

In fact, searching the sources for "beginsWith: 'test'", the logic is
duplicated quite a bit. And someone even snuck your proposed change into
CompiledMethod>>#isTestMethod, so now we already have two conflicting
concepts of what a test selector is in Core.

In fact, I already did the changes in an image (but not published, I wait for feedback) and I also noticed the duplicated logic.

What I did is really simple:
  • In TestCase Class,
    • add 
<Capture d’écran 2015-04-21 à 10.12.36.png>

hi, side note: 
take into account that the use of #or: as you are using it is not recommended. 
Better something like: 

firstTerm 
or: [ secondTerm 
or: [ thirdTerm 
or [ etc. ] ] ]

yes, is uglier, but faster :)


ok ;)

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sean P. DeNigris
Administrator
In reply to this post by Miguel Moquillon
Miguel Moquillon wrote
BDD and TDD stands for different purposes with different actors...
While that's unfortunately often true in practice, there is no difference philosophically. [T|B]DD "done right" always focuses on the user. But because of the word "test" in TDD, many tests (including many in our image) became incomprehensible from a "how do I use this library" POV, tested internal implementation details, etc. So BDD was invented to make the focus on behaviors explicit and to guide us all toward best practice. It also quite nicely unified acceptance testing and unit testing.

The "In order to..." that you're describing is the outer, high-level acceptance test that in Ruby for example might be written with Cucumber. But once one has a failing acceptance test, the next step in BDD is to drop down into e.g. RSpec and write something a lot closer to a unit test, often mocking out collaborators to drive creation of an API.

In summary, the intent of BDD is to be "TDD Done Right". There is no inherent conflict, and no specific tools are technically required. Although, since as McLuhan suggested, we become our tools, so obviously the proper tools may be decisive, especially when first learning.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey

Le 21 avr. 2015 à 13:44, Sean P. DeNigris a écrit :

> Miguel Moquillon wrote
>> BDD and TDD stands for different purposes with different actors...
>
> While that's unfortunately often true in practice, there is no difference
> philosophically. [T|B]DD "done right" always focuses on the user. But
> because of the word "test" in TDD, many tests (including many in our image)
> became incomprehensible from a "how do I use this library" POV, tested
> internal implementation details, etc. So BDD was invented to make the focus
> on behaviors explicit and to guide us all toward best practice. It also
> quite nicely unified acceptance testing and unit testing.
>
> The "In order to..." that you're describing is the outer, high-level
> acceptance test that in Ruby for example might be written with Cucumber. But
> once one has a failing acceptance test, the next step in BDD is to drop down
> into e.g. RSpec and write something a lot closer to a unit test, often
> mocking out collaborators to drive creation of an API.
this one is often called the outside - in loop (ref: http://dannorth.net/whats-in-a-story/).
Even is the outside - in loop is not used, I find valuable to encourage people to name (and write) their unit tests in terms of behavior.
       

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Miguel Moquillon
In reply to this post by Sean P. DeNigris
Le 21/04/2015 13:44, Sean P. DeNigris a écrit :

> Miguel Moquillon wrote
>> BDD and TDD stands for different purposes with different actors...
> While that's unfortunately often true in practice, there is no difference
> philosophically. [T|B]DD "done right" always focuses on the user.
> [...]
> The "In order to..." that you're describing is the outer, high-level
> acceptance test that in Ruby for example might be written with Cucumber. But
> once one has a failing acceptance test, the next step in BDD is to drop down
> into e.g. RSpec and write something a lot closer to a unit test, often
> mocking out collaborators to drive creation of an API.
>
> In summary, the intent of BDD is to be "TDD Done Right".
I don't agreed with your assumption: there is a difference
philosophically both in theory and in practice.
The word 'Test' in TDD doesn't mean its purpose is to test; it is a
misconception. In fact TDD is a method for developers to focus on the
design of their code by avoiding over-designing.
In other side, BDD stands for test, more exactly functional testing. It
is a safety belt to
avoid both functional regressions and to ensure the written code is
valid according to
the requirements.

So, when a functional test failed, the next step in BDD is to pass the
control to the developer to fix the issue whatever
its method (BDD don't cover this level).
They are not related but, as you wrote in your example with Ruby, they
can be used both in a project, at a different level. BDD doesn't imply
TDD but yes, in practice, they are often used in conjunction.

Now, some tools were inspired by BDD to provide the developers a better
way to express unit tests (RSpec for example), to be more focused on the
design, but they are in fact more related to TDD than BDD. Don't
confound the approach with the tools.

> There is no
> inherent conflict, and no specific tools are technically required. Although,
> since as McLuhan suggested, we become our tools, so obviously the proper
> tools may be decisive, especially when first learning.
There is no conflicts between TDD and BDD because they are not related
and they are not concurrent.
In fact they can be used both but at different level. The same with the
tools.
Beside that, I have a principle: don't learn an approach through a tool.
But use a tool
to facilitate the application of the approach. And as you wrote, indeed,
the proper tool is important.

Miguel Moquillon


Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

Sean P. DeNigris
Administrator
Miguel Moquillon wrote
> In summary, the intent of BDD is to be "TDD Done Right".
I don't agreed with your assumption: there is a difference
philosophically both in theory and in practice.
In actuality, it is a bit overstated, because one key insight of BDD was to bring /all/ stakeholders into TDD. "In order that... as a... I want..." was intended as a way to have the customer write a spec that would become an executable part of the test framework. But, they're also not as totally independent as you describe. In fact, Dan North, the inventor of BDD has explained it such - that BDD = TDD if your whole team are programmers, but BDD includes: TDD if the stakeholders include non-programmers.
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

stepharo
In reply to this post by demarey
Christophe

I do not have the answer just the constraints.
This is hyper important that the solution does not change much SUnit.
This way we do not end up with a mess with Sunit version.

It is better to have a separate package.

Stef

Le 20/4/15 13:02, Christophe Demarey a écrit :

> Hi,
>
> With BDD a current test practice is to start method names with 'should'.
> It is not yet possible in Pharo but easily do-able (update of TestCase and some Nautilus methods).
> I would like that Pharo detects tes methods all methods of a class subclassing (directly or not) TestCase AND starting with either 'test' or 'should'.
> I also would like to add 'deny' to not use 'shouldNot' but here I'm not sure.
>
> WDYT?
>
> Christophe.
>


Reply | Threaded
Open this post in threaded view
|

Re: TDD and BDD

demarey

Le 22 avr. 2015 à 20:19, stepharo a écrit :

> Christophe
>
> I do not have the answer just the constraints.
> This is hyper important that the solution does not change much SUnit.
> This way we do not end up with a mess with Sunit version.
>
> It is better to have a separate package.

I ckecked and we already diverged a lot from the SUnit standard (use of Traits, announcements, etc.).
Do you want I integrate the refactoring to have the test selectors selection coherent?
If yes, my proposal just adds 'or: [ selector name beginsWith: 'should' ]. I do not see the point of having a separate package.
If no, does it mean that we should never touch the SUnit package?

smime.p7s (5K) Download Attachment
12