Thanks a lot, Dan.

Jeremy,

The approach is a bit different, using Cucumber Spec Transformers instead of 
auxiliary services.

For a test relating an "Event" entity, like:

Given there is an event with name "Hurricane"
....


The Glue looks like:

    @Given(".*there is.* an (event with name \"[^\"]*\")$")
    public void given_event(@Transform(EntityNullAllowingTransformer.class) 
Event event) throws Throwable {

        if (event == null) {
            event = 
this.wrap(this.service(Events.class)).createEvent(EntityNullAllowingTransformer.getLastCapturedId(),
 null, true, false);
        }

        this.putVar("event", EntityNullAllowingTransformer.getLastCapturedId(), 
event);
    }


The Transformer tries to "deduce" the entity type, the field and the value from 
the Gherkin's capture. So, instead of capturing just the text between " " , it 
captures also the context, i.e.:
 event with name \"[^\"]*\"

From there, it tries to know the entity type ("event"), the id field to search 
on ("name") and the value to search for (the text between " ").

The default implementation works by recognizing the previous pattern with 
slight variations ("reference" or "id" instead of "name"), but can be 
subclassed and extended for custom patterns. 

Regarding the Entity's name ("event") it works due to the fact that internally, 
Isis saves for each entity a singular name and a plural name.
By default, if not annotated, from a class "Customer", it will internally 
associate with it the singular name "Customer" and the plural name "Customers". 
And also, if the name would be "CustomerInvoice", it would properly generate 
"Customer Invoice" (with a space) and "Customer Invoices".

This automatically-generated names can be modified by the @Named and @Plural 
annotation.

So if you use the Ubiquitous Language on your class names and your BDD tests, a 
match can be done. 

Inside the Glue code, the intent is to directly use any domain's code, such as 
factory methods, actions, etc. without needing custom services.

As I wanted to handle nullable and non-nullable entities (mainly for detecting 
"typo" errors where the Entity should exist) I implemented 2 variants: 
EntityNullAllowingTransformer and EntityNullDisallowingTransformer (named based 
on Estatio's NullRecognizingTransformer. If another name is better, please, 
tell me :-)

It does not allow neither passing "null"  as the string, or the query not 
returning any results.

For example, a mandatory event on a Glue would be defined as:

    @Given("^the (event with name \"[^\"]*\") has over business processes the 
(likelihood level with name \"[^\"]*\")$")
    public void 
the_event_has_over_business_processes_the_likelihood_level(@Transform(EntityNullDisallowingTransformer.class)
 final Event event, @Transform(EntityNullDisallowingTransformer.class) final 
LikelihoodLevel likelihoodLevel) {

        event.setLikelihoodLevelOverBusinessProcesses(likelihoodLevel);

    }



Instead, you've used a @NotNull annotation, which it's a better alternative. 
But javax.validation is neither used by Isis nor the Quickstart archetype, so 
not sure if it's better just to leave it with 2 classes...

Any ideas about how to improve it?

Regards,

Oscar




El 12/09/2013, a las 22:19, Jeremy Gurr <jere...@infusionsoft.com> escribió:

> Oscar,
> 
> The generic Spec Transformer looks interesting. I couldn't quite figure out 
> how it would be used. Maybe you could give an example test case?
> 
> What I've got working right now can drive tests like the following:
> 
> Scenario: A new topping is added
> Given these toppings exist:
> | topping name    | price |
> | Pepperoni       | 1.00  |
> | Extra Cheese    | 1.25  |
> When new toppings are created:
> | topping name    | price |
> | Pineapple       | 0.50  |
> Then these toppings will remain:
> | topping name    | price |
> | Pepperoni       | 1.00  |
> | Extra Cheese    | 1.25  |
> | Pineapple       | 0.50  |
> 
> The cool part is that "topping" and "toppings" are parameterized, as well as 
> the field names, so I can use any domain entity without having to change the 
> glue. It will work with any number of rows or field names. I suspect this is 
> similar to what you are working on.
> 
> Of course this only tests the most basic of features, but I suspect it 
> wouldn't be too hard to extend this to meet work with many different kinds of 
> entity tests.
> 
> My glue code looks like this:
> 
> @Given("^these ([\\w ]+) exist:$")
> public void initializeEntities(@NotNull String niceServiceName, @NotNull 
> List<Map<String, String>> entitiesToAdd) throws Throwable {
> if (entitiesToAdd.size() > 0) {
> final Class<? extends DataEntityService> serviceClass = 
> dataEntityUtil.getDataEntityServiceClass(niceServiceName);
> final DataEntityService service = service(serviceClass);
> service.clear();
> createEntities(niceServiceName, entitiesToAdd);
> }
> }
> 
> @When("^new ([\\w ]+) are created:$")
> public void createEntities(@NotNull String niceServiceName, @NotNull 
> List<Map<String, String>> entitiesToAdd) throws Throwable {
> final Class<? extends DataEntityService> serviceClass = 
> dataEntityUtil.getDataEntityServiceClass(niceServiceName);
> final DataEntityService service = service(serviceClass);
> for (Map<String, String> entityMap : entitiesToAdd) {
> final DataEntity entity = dataEntityUtil.convertToEntity(service, entityMap);
> service.makePersistent(entity);
> }
> }
> 
> @Then("^these ([\\w ]+) will remain:$")
> public void assertEntitiesExist(@NotNull String niceServiceName, @NotNull 
> List<Map<String, String>> entitiesWillExist) throws Throwable {
> final Class<? extends DataEntityService> serviceClass = 
> dataEntityUtil.getDataEntityServiceClass(niceServiceName);
> final DataEntityService service = service(serviceClass);
> 
> for (Map<String, String> entityMap : entitiesWillExist) {
> Assert.assertTrue("Entity doesn't exist", 
> dataEntityUtil.entityExists(service, entityMap));
> }
> }
> 
> I am still quite new to ISIS and Cucumber, so any advice on how this can be 
> improved is more than welcome.
> 
> -- Jeremy
> 
> On Sep 12, 2013, at 11:23 AM, GESCONSULTOR - Óscar Bou wrote:
> 
> 
> Same happened to a mate upgrading to the latest snapshot.
> 
> A default value as suggested by Jeremy would be ok.
> 
> Jeremy, did you see the mail at [1] ?
> 
> It's intent was to solve your idea of a "generic" Spec Transformer for Isis 
> entities. There I copied the code of a generic class.
> I'm testing an improved version  and plan to commit it next week (in fact, 1 
> abstract class with 2 specializations; one allowing null entities, and one 
> throwing an exception if the referenced object is not found - as normally is 
> a "transcription" problem).
> 
> If you want to previously access it, don't hesitate to ask and I can attach 
> current version to a JIRA ticket.
> 
> HTH,
> 
> Oscar
> 
> 
> 
> 
> [1] 
> http://markmail.org/search/isis-users+list:org.apache.incubator.isis-users#query:isis-users%20list%3Aorg.apache.incubator.isis-users%20from%3A%22GESCONSULTOR%20-%20%C3%93scar%20Bou%22+page:9+mid:tibcgc45fii566w3+state:results
> 
> 

Reply via email to