On 8 September 2013 09:21, GESCONSULTOR - Óscar Bou
<[email protected]>wrote:

>
> That sounds really nice...
>
>
>
> Are stress tests also included, in addition to regression tests?
>

Not sure.  Perhaps.  It'll probably depend on how well the selenium
webdrivers work.  I was thinking that using Chrome driver  [2] is good for
developing the tests (can see stuff happening), but that ghostdriver /
phantomjs [3] is probably the way to go for CI and for stress tests.



>
> That raised on the list the previous weeks.  It will be really interesting
> to know if there are any concurrency issues at Wicket, Isis or DN.
>

Isis does - in the Oid - have full support for detecting concurrency
violations, as does DataNucleus if mapped correctly.

If there are issues, it'll be because Oids encoded in the Wicket page are
stale and need refreshing.  This might mean removing some of the ajax in
the viewer and just doing a redirect-after-post to force a page refresh.



>
> Seems that Selenium can also be used in a grid configuration to simulate
> stress load tests.
>

Yup, I believe so.



>
> The creator of Selenium has founded also a company specialized on web
> stress tests [1]. As it's integrated with Amazon Web Services, you can
> configure your stress environment (and pay for it).
>

Yeah, I'm aware of that.  Will depend on how robust the geb framework is.
 Over in Ireland we're doing something similar using a framework called
Coypu.  This also sits on top of Selenium.  Our experience is that Selenium
by itself can be fragile but a layer on top - such as Coypu - can make it
much more stable by doing automatic retries.  What I I don't know is how
good geb is at doing that also.



>
> [snip]
>
>
Cheers
Dan


[2] https://code.google.com/p/selenium/wiki/ChromeDriver
[3] https://github.com/detro/ghostdriver




>
>
> El 08/09/2013, a las 09:45, Dan Haywood <[email protected]>
> escribió:
>
> > That's fine with me.
> >
> > This week I'm starting to look at automated web browser tests (possibly
> > using Geb [1] as a layer over Selenium).  Plan is for Estatio to act as a
> > regression suite for Isis as a whole.  So no immediate rush my end.
> >
> > Cheers
> > Dan
> >
> >
> > [1] http://www.gebish.org/
> >
> >
> > On 8 September 2013 08:35, GESCONSULTOR <[email protected]> wrote:
> >
> >> For sure!
> >>
> >> Unless you or Jeremy plan to use it immediately let me check and improve
> >> it this week through some BDD features we must implement.
> >>
> >> Thanks,
> >>
> >> Oscar
> >>
> >>
> >> El 08/09/2013, a las 09:20, Dan Haywood <[email protected]>
> >> escribió:
> >>
> >>> Looks very good, Oscar, exactly the sort of thing that should be in the
> >>> framework, I think.
> >>>
> >>> Could you raise a ticket and provide a commit?  If you have the time,
> >>> perhaps you could also refactor the ToDo app to show its use?
> >>>
> >>> Many thanks
> >>>
> >>> Cheers
> >>> Dan
> >>>
> >>>
> >>>
> >>> On 7 September 2013 19:05, GESCONSULTOR - Óscar Bou
> >>> <[email protected]>wrote:
> >>>
> >>>>
> >>>> I've just been thinking about a way to avoid to define a Spec
> >> Transformer
> >>>> for every Entity class in the Domain.
> >>>>
> >>>> As it's just "infrastructure software", I thought that was "just
> >> enough".
> >>>>
> >>>> The attached code allows to use just one Spec Transformer when the
> Glue
> >> is
> >>>> written like this:
> >>>> -  the employee with name "PETER"
> >>>> - the employee named "PETER"
> >>>> - the property with reference "REF-001"
> >>>> - the property referenced "REF-001"
> >>>> - the product with id "PR-001"
> >>>>
> >>>> From there, we know that:
> >>>> - The Entity singular name is "employee" (so it can be obtained from
> the
> >>>> Isis Object Specifications, reinforcing the Ubiquitous Language use on
> >> BDD
> >>>> specifications).
> >>>> - We must search by name
> >>>> - The name must be PETER
> >>>>
> >>>>
> >>>>
> >>>> For using it, I must define a Glue like this one:
> >>>>
> >>>> Define a Glue like this one:
> >>>> @When("The company (employee with name \"[^\"]*\") has a role
> assigned")
> >>>> public void
> >>>>
> >>
> the_company_employee_with_name(@Transform(GenericIsisJdoTransformer.class)
> >>>> final  Employee employee) {
> >>>>  ...
> >>>> }
> >>>>
> >>>>
> >>>>
> >>>> First "proof-of-concept" code version follows this text.
> >>>>
> >>>> It can be improved in many ways, for allowing customization through
> >>>> inheritance, avoiding JDO through the use of the Apache Isis query
> >> methods,
> >>>> etc.
> >>>>
> >>>>
> >>>> But I would let you know, right to know if you think it can be useful.
> >>>>
> >>>> On this way, the only implemented classes  are the ones supporting the
> >>>> Glues (and only the Spec Transformers for more specific use cases).
> >>>>
> >>>>
> >>>> HTH,
> >>>>
> >>>> Oscar
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> ---------------------
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> package com.xms.framework.testing.integration.spectransformers;
> >>>>
> >>>> import java.util.HashMap;
> >>>> import java.util.Map;
> >>>> import java.util.regex.Matcher;
> >>>> import java.util.regex.Pattern;
> >>>>
> >>>> import javax.jdo.Query;
> >>>>
> >>>> import org.opensaml.artifact.InvalidArgumentException;
> >>>>
> >>>> import org.apache.isis.applib.DomainObjectContainer;
> >>>> import org.apache.isis.core.metamodel.spec.ObjectSpecification;
> >>>> import org.apache.isis.core.runtime.system.context.IsisContext;
> >>>> import org.apache.isis.core.specsupport.scenarios.ScenarioExecution;
> >>>> import
> >>>>
> >>
> org.apache.isis.objectstore.jdo.datanucleus.service.support.IsisJdoSupportImpl;
> >>>>
> >>>> /**
> >>>> * Requires the Gherkin's capture in the format '([entitySingularName]
> >>>> [(.+?)
> >>>> * name(d)|(.+?) reference|(.+?) id] \"[entityId]\")'.
> >>>> * <p>
> >>>> * For example:
> >>>> * <ul>
> >>>> * <li>the employee with name "PETER"</li>
> >>>> * <li>the employee named "PETER"</li>
> >>>> * <li>the property with reference "REF-001"</li>
> >>>> * <li>the property referenced "REF-001"</li>
> >>>> * <li>the product with id "PR-001"</li>
> >>>> * </ul>
> >>>> * <p>
> >>>> * For matching the first one we will need the following Gherkin
> regular
> >>>> * expression:
> >>>> * <ul>
> >>>> * <li>
> >>>> * \\@When("The company's (employee with name \"[^\"]*\") has a role
> >>>> assigned")</li>
> >>>> * </ul>
> >>>> * <p>
> >>>> * From there, we know that:
> >>>> * <ul>
> >>>> * <li>The Entity singular name is "employee".</li>
> >>>> * <li>We must search by name</li>
> >>>> * <li>The name must be PETER</li>
> >>>> * </ul>
> >>>> *
> >>>> */
> >>>> public class GenericIsisJdoTransformer extends
> >>>> NullRecognizingTransformer<Object> {
> >>>>
> >>>>   private static Map<String, ObjectSpecification>
> >>>> specificationsBySingularName;
> >>>>
> >>>>   /**
> >>>>    * Tries to obtain the Entity class name, id and search field from
> >> the
> >>>>    * Cucumber capture, and find it on the JDO Object Store.
> >>>>    *
> >>>>    * @see com.xms.framework.testing.integration.spectransformers.
> >>>>    *
>  NullRecognizingTransformer#transformNonNull(java.lang.String)
> >>>>    */
> >>>>   @Override
> >>>>   protected Object transformNonNull(final String capture) {
> >>>>
> >>>>       return this.findFromCapture(capture);
> >>>>
> >>>>   }
> >>>>
> >>>>   /**
> >>>>    * @param entityName
> >>>>    *            Name of the Entity specified on the Gherkin's capture.
> >>>>    * @return
> >>>>    */
> >>>>   private ObjectSpecification specificationOf(final String entityName)
> >> {
> >>>>
> >>>>       if (IsisJdoTransformer.specificationsBySingularName == null) {
> >>>>           IsisJdoTransformer.specificationsBySingularName = new
> >>>> HashMap<String, ObjectSpecification>();
> >>>>
> >>>>           for (final ObjectSpecification current :
> >>>> IsisContext.getSpecificationLoader().allSpecifications()) {
> >>>>
> >>>>
> >>>>
> >>
> IsisJdoTransformer.specificationsBySingularName.put(current.getSingularName().toLowerCase(),
> >>>> current);
> >>>>           }
> >>>>
> >>>>       }
> >>>>       return
> >>>>
> >>
> IsisJdoTransformer.specificationsBySingularName.get(entityName.toLowerCase());
> >>>>
> >>>>   }
> >>>>
> >>>>   private final Class<?> entityClassFrom(final String capture) {
> >>>>
> >>>>       // The Entity Id will be between "".
> >>>>       String entityName = "";
> >>>>
> >>>>       final String[] recognizedPatterns = { "( with name )", "( named
> >>>> )", "( with reference )", "( referenced )", "( with id )" };
> >>>>
> >>>>       for (final String currentPattern : recognizedPatterns) {
> >>>>           final Pattern p = Pattern.compile(currentPattern);
> >>>>           final Matcher m = p.matcher(capture);
> >>>>           if (m.find()) {
> >>>>               entityName = capture.substring(0, m.start());
> >>>>               break;
> >>>>           }
> >>>>       }
> >>>>
> >>>>       if (entityName == "") {
> >>>>           throw new InvalidArgumentException(String.format("Cannot
> find
> >>>> the entity's name on the capture %s. The format must be
> >>>> '([entitySingularName] [with name|with reference|named|referenced]
> >>>> \"[entityId]\")'", capture));
> >>>>       }
> >>>>
> >>>>       final ObjectSpecification specification =
> >>>> this.specificationOf(entityName);
> >>>>       if (specification == null) {
> >>>>           throw new InvalidArgumentException(String.format("There is
> no
> >>>> Entity registered in Isis with '%s' as it's singular name",
> >> entityName));
> >>>>       }
> >>>>       return specification.getCorrespondingClass();
> >>>>
> >>>>   }
> >>>>
> >>>>   /**
> >>>>    * @param capture
> >>>>    *            The Gherkin's capture
> >>>>    * @return
> >>>>    */
> >>>>   private final String filterFrom(final String capture) {
> >>>>       // Find by "name".
> >>>>       if (capture.matches("(.+?)name(.+?)")) {
> >>>>           return String.format("name==\"%s\"",
> >>>> this.entityIdFrom(capture));
> >>>>       }
> >>>>
> >>>>       // Find by "reference".
> >>>>       if (capture.matches("(.+?)reference(.+?)")) {
> >>>>           return String.format("reference==\"%s\"",
> >>>> this.entityIdFrom(capture));
> >>>>       }
> >>>>
> >>>>       // Find by "id".
> >>>>       if (capture.matches("(.+?)id(.+?)")) {
> >>>>           return String.format("id==\"%s\"",
> >> this.entityIdFrom(capture));
> >>>>       }
> >>>>
> >>>>       throw new InvalidArgumentException(String.format("The entity id
> >>>> has not been found on the capture '%s'. It must be between two \"
> >>>> characters.", capture));
> >>>>   }
> >>>>
> >>>>   private final Object entityIdFrom(final String capture) {
> >>>>       // The Entity Id will be between "".
> >>>>       final Pattern p = Pattern.compile("\"(.+?)\"");
> >>>>       final Matcher m = p.matcher(capture);
> >>>>       if (m.find()) {
> >>>>           return m.group().replace("\"", "");
> >>>>       } else {
> >>>>           throw new InvalidArgumentException(String.format("The entity
> >>>> id has not been found on the capture '%s'. It must be between two \"
> >>>> characters.", capture));
> >>>>       }
> >>>>   }
> >>>>
> >>>>   private final Object findFromCapture(final String capture) {
> >>>>
> >>>>       // Need to flush().
> >>>>       // The Entity can be created on the same transaction.
> >>>>       // If we don't flush() the changes, perhaps the entity have not
> >>>> been
> >>>>       // saved to the object store yet, and will not be found.
> >>>>
> >>>>
> >>
> ScenarioExecution.current().service(DomainObjectContainer.class).flush();
> >>>>
> >>>>       final Query query =
> >>>>
> >>
> ScenarioExecution.current().service(IsisJdoSupportImpl.class).getJdoPersistenceManager().newQuery();
> >>>>       query.setClass(this.entityClassFrom(capture));
> >>>>       query.setFilter(this.filterFrom(capture));
> >>>>       query.setUnique(true);
> >>>>
> >>>>       final Object result = query.execute();
> >>>>
> >>>>       return result;
> >>>>
> >>>>   }
> >>>> }
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> ---------------------
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> El 27/08/2013, a las 20:24, Kevin Meyer - KMZ <[email protected]>
> >> escribió:
> >>>>
> >>>>> Hi Jeremy,
> >>>>>
> >>>>> If I remember correctly, Dan has examples for overriding the "Finder"
> >>>>> methods in the ToDo demo / artefact that use JDO search classes to
> >>>>> build queries.
> >>>>>
> >>>>> In fact:
> >>>>>
> >>>>> In the  "ToDoItemsJdo" class (which extends an
> >>>>> AbstractFactoryAndRepository):
> >>>>>  // {{ notYetComplete (action)
> >>>>>  @Override
> >>>>>  protected List<ToDoItem> doNotYetComplete() {
> >>>>>      return allMatches(
> >>>>>              new QueryDefault<ToDoItem>(ToDoItem.class,
> >>>>>                      "todo_notYetComplete",
> >>>>>                      "ownedBy", currentUserName()));
> >>>>>  }
> >>>>>  // }}
> >>>>>
> >>>>> This appears in an old copy of the repo I have in the wicket JDO
> >>>>> quickstart project.
> >>>>>
> >>>>> So while you can't use "FindByPattern", JDO has implemented a
> >>>>> useful alternative.
> >>>>>
> >>>>> Regards,
> >>>>> Kevin
> >>>>>
> >>>>>
> >>>>> On 27 Aug 2013 at 14:37, Jeremy Gurr wrote:
> >>>>>
> >>>>>> I'm playing around with the cucumber support tools in isis (a
> testing
> >>>> framework for behavior driven development, for those who don't know),
> >> and
> >>>> have created a test that basically looks like this:
> >>>>>>
> >>>>>> <snip>
> >>>>>>
> >>>>>> It's very convenient that cucumber instantiates my ServiceClass
> model
> >>>> object and automatically plugs in fields according to the feature spec
> >>>> column header. This enables me to add new fields simply by adding a
> >> column
> >>>> in the spec, and adding the corresponding column in my model object.
> It
> >>>> skips the extra hassle of having to update the glue code as well as
> >> service
> >>>> methods to construct the object.
> >>>>>>
> >>>>>> The "exists" method contains this code:
> >>>>>>
> >>>>>> public boolean exists(ServiceClass serviceClass) {
> >>>>>> final QueryFindByPattern<ServiceClass> query = new
> >>>> QueryFindByPattern<ServiceClass>(ServiceClass.class, serviceClass);
> >>>>>> final ServiceClass firstMatch = firstMatch(query);
> >>>>>>
> >>>>>> return firstMatch != null;
> >>>>>> }
> >>>>>>
> >>>>>> I'm just trying to verify that an object exists with fields matching
> >>>> the incoming object, some fields of which may be null, meaning that
> they
> >>>> can be any value. The QueryFindByPattern class seemed to be a perfect
> >> fit
> >>>> since I'm passing around ServiceClass instances anyway. However,
> >> running it
> >>>> executes code that is not yet implemented:
> >>>>>>
> >>>>>> <snip>
> >>>>
> >>>>
> >>
>
>

Reply via email to