You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/04/24 16:07:00 UTC

[2/3] isis git commit: ISIS-1139: updating asciidocs with info on ObjectContracts.

ISIS-1139: updating asciidocs with info on ObjectContracts.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/5e33aa8e
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/5e33aa8e
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/5e33aa8e

Branch: refs/heads/master
Commit: 5e33aa8e61519514c9d4ed18d5505a8a231f9898
Parents: 8cec3ca
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 24 15:05:35 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Apr 24 15:05:35 2015 +0100

----------------------------------------------------------------------
 ...-guide-reference-applib-utility-classes.adoc | 138 ++++++++++++-
 .../user-guide-reference-cmd-line-args.adoc     |  15 ++
 .../user-guide-reference-web-xml.adoc           |   8 +
 .../user-guide/user-guide-reference.adoc        |   6 +-
 ...er-guide-testing-bdd-integ-test-support.adoc |   7 +
 .../user-guide-testing-fake-data.adoc           |  11 +
 .../user-guide-testing-fixture-scripts.adoc     |  65 ++++++
 .../user-guide-testing-integ-test-support.adoc  |  19 ++
 .../user-guide-testing-unit-test-support.adoc   | 200 +++++++++++++++++++
 .../asciidoc/user-guide/user-guide-testing.adoc |  62 +-----
 adocs/template/document.html.erb                |  22 +-
 11 files changed, 491 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
index 175dbfc..f684ebe 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-applib-utility-classes.adoc
@@ -3,6 +3,142 @@
 :_basedir: ../
 :_imagesdir: images/
 
-IMPORTANT: TODO
+The `org.apache.isis.applib.util` package has a number of simple utility
+classes designed to simplify the coding of some common tasks.
 
+== Title creation
 
+The `TitleBuffer` utility class is intended to make it easy to construct
+title strings (returned from the `title()` method). For example, it has
+overloaded versions of methods called `append()` and `concat()`.
+
+== Reason text creation (for disable and validate methods)
+
+There are two different classes provided to help build reasons returned
+by `disableXxX()` and `validateXxx()` methods:
+
+* the `org.apache.isis.applib.util.ReasonBuffer` helper class
+* the `org.apache.isis.applib.util.Reasons` helper class
+
+For example:
+
+[source,java]
+----
+public class Customer {
+    ...
+    public String validatePlaceOrder(Product p, int quantity) {
+        return Reasons.coalesce(
+            whetherCustomerBlacklisted(this),
+            whetherProductOutOfStock(p)
+        );
+    }
+}
+----
+
+Which you use (if any) is up to you.
+
+== ObjectContracts
+
+The `ObjectContracts` test provides a series of methods to make it easy for your domain objects to:
+
+* implement `Comparable` (eg so can be stored in ``java.util.SortedSet``s)
+* implement `toString()`
+* implement `equals()`
+* implement `hashCode()`
+
+For example:
+
+[source,java]
+----
+public class ToDoItem implements Comparable<ToDoItem> {
+
+    public boolean isComplete() { ... }
+    public LocalDate getDueBy() { ... }
+    public String getDescription() { ... }
+    public String getOwnedBy() { ... }
+
+    public int compareTo(final ToDoItem other) {
+        return ObjectContracts.compare(this, other, "complete","dueBy","description");
+    }
+
+    public String toString() {
+        return ObjectContracts.toString(this, "description","complete","dueBy","ownedBy");
+    }
+}
+----
+
+[WARNING]
+====
+Note that `ObjectContracts` makes heavy use of Java Reflection.  While it's great to get going quickly in prototyping, we recommend you use your IDE to code generate implementations of these methods for production code.
+
+Moreover (and perhaps even more importantly) `ObjectContracts` implementation can cause DataNucleus to recursively rehydrate a larger number of associated entities (More detail below).
+
+We therefore recommend that you disable persistence-by-reachability by adding:
+
+[source,ini]
+.persistor_datanucleus.properties
+----
+#
+# Require explicit persistence (since entities are Comparable and using ObjectContracts#compareTo).
+#
+isis.persistor.datanucleus.impl.datanucleus.persistenceByReachabilityAtCommit=false
+----
+
+====
+
+### Explanation of the issue in more detail
+
+Consider the entities:
+
+    Party <->* AgreementRole <*-> Agreement
+
+In the course of a transaction, the `Agreement` entity is loaded into memory (not necessarily modified), and then new ``AgreementRole``s are associated to it.
+
+All these entities implement `Comparable` using `ObjectContracts`, so that the implementation of ``AgreementRole``'s (simplified) is:
+
+[source,java]
+----
+public class AgreementRole {
+    ...
+    public int compareTo(AgreementRole other) {
+        return ObjectContracts.compareTo(this, other, "agreement","startDate","party");
+    }
+    ...
+}
+----
+
+while ``Agreement``'s is implemented as:
+
+[source,java]
+----
+    public class Agreement {
+        ...
+        public int compareTo(Agreement other) {
+            return ObjectContracts.compareTo(this, other, "reference");
+        }
+        ...
+    }
+----
+
+and ``Party``'s is similarly implemented as:
+
+[source,java]
+----
+public class Party {
+    ...
+    public int compareTo(Party other) {
+        return ObjectContracts.compareTo(this, other, "reference");
+    }
+    ...
+}
+----
+
+DataNucleus's persistence-by-reachability algorithm adds the ``AgreementRole``s into a `SortedSet`, which causes `AgreementRole#compareTo()` to fire:
+
+* the evaluation of the "agreement" property delegates back to the `Agreement`, whose own `Agreement#compareTo()` uses the scalar `reference` property.  As the `Agreement` is already in-memory, this does not trigger any further database queries
+
+* the evaluation of the "startDate" property is just a scalar property of the `AgreementRole`, so will already in-memory
+
+* the evaluation of the "party" property delegates back to the `Party`, whose own `Party#compareTo()` requires the uses the scalar `reference` property.  However, since the `Party` is not yet in-memory, using the `reference` property triggers a database query to "rehydrate" the `Party` instance.
+
+In other words, figuring out whether `AgreementRole` is comparable requires the persistence-by-reachability algorithm to run, causing the adjacent associated entity `Party` to also be retrieved.

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
new file mode 100644
index 0000000..06e5cc8
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-cmd-line-args.adoc
@@ -0,0 +1,15 @@
+= Command Line Arguments
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## `org.apache.isis.WebServer`
+
+For example:
+* `--fixture`
+* `--services`
+
+etc...
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
new file mode 100644
index 0000000..bc6da88
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference-web-xml.adoc
@@ -0,0 +1,8 @@
+= web.xml Configuration
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
index 07ed17d..caea6de 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-reference.adoc
@@ -15,9 +15,11 @@ include::user-guide-reference-domain-services.adoc[leveloffset=+1]
 
 include::user-guide-reference-value-types.adoc[leveloffset=+1]
 
-## Applib Utility Classes
-
 include::user-guide-reference-applib-utility-classes.adoc[leveloffset=+1]
 
 include::user-guide-reference-convenience-superclasses.adoc[leveloffset=+1]
 
+include::user-guide-reference-cmd-line-args.adoc[leveloffset=+1]
+
+include::user-guide-reference-web-xml.adoc[leveloffset=+1]
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
new file mode 100644
index 0000000..714abc5
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-bdd-integ-test-support.adoc
@@ -0,0 +1,7 @@
+= BDD/Integ Test Support
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
new file mode 100644
index 0000000..a31b65b
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fake-data.adoc
@@ -0,0 +1,11 @@
+= Fake Data
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+WARN: Isis Addons, not ASF.
+
+link:https://github.com/isisaddons/isis-module-fakedata
+

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
new file mode 100644
index 0000000..d4d3ffe
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-fixture-scripts.adoc
@@ -0,0 +1,65 @@
+= Fixture Scripts
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## API and Usage
+
+IMPORTANT: TODO
+
+## SudoService (1.9.0-SNAPSHOT)
+
+Sometimes in our fixture scripts we want to perform a business action runnin as a particular user.  This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
+
+An example of the latter case is in the link:[todoapp]'s `ToDoItem` class:
+
+[source,java]
+.Production code that depends on current user
+----
+public ToDoItem newToDo(
+        @Parameter(regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*") @ParameterLayout(named="Description")
+        final String description,
+        @ParameterLayout(named="Category")
+        final Category category,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Subcategory")
+        final Subcategory subcategory,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Due by")
+        final LocalDate dueBy,
+        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Cost")
+        final BigDecimal cost) {
+    return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
+}
+private String currentUserName() {
+    return container.getUser().getName(); // <1>
+}
+----
+<1> is the current user.
+
+The fixture for this can use the `SudoService` to run a block of code as a specified user:
+
+[source,java]
+.Fixture Script
+----
+final String description = ...
+final Category category = ...
+final Subcategory subcategory = ...
+final LocalDate dueBy = ...
+final BigDecimal cost = ...
+final Location location = ...
+
+toDoItem = sudoService.sudo(username,
+        new Callable<ToDoItem>() {
+            @Override
+            public ToDoItem call() {
+                final ToDoItem toDoItem = wrap(toDoItems).newToDo(
+                        description, category, subcategory, dueBy, cost);
+                wrap(toDoItem).setLocation(location);
+                return toDoItem;
+            }
+        });
+----
+
+Behind the scenes the `SudoService` simply talks to the `DomainObjectContainer` to override the user returned by the `getUser()` API.  It is possible to override both users and roles.

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
new file mode 100644
index 0000000..399c2e7
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-integ-test-support.adoc
@@ -0,0 +1,19 @@
+= Integration Test Support
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+IMPORTANT: TODO
+
+
+## Introduction
+
+IMPORTANT: TODO
+
+## Using the WrapperFactory
+
+IMPORTANT: TODO
+
+## IsisConfigurationForJdoIntegTests
+
+IMPORTANT: TODO

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
new file mode 100644
index 0000000..fefae90
--- /dev/null
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing-unit-test-support.adoc
@@ -0,0 +1,200 @@
+= Unit Test Support
+:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+:_basedir: ../
+:_imagesdir: images/
+
+Isis Core provides a number of unit test helpers for you to use (if you wish) to test your domain objects.  To use, update the `pom.xml`:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.isis.core</groupId>
+    <artifactId>isis-core-unittestsupport</artifactId>
+    <scope>test</scope> // <1>
+</dependency>
+----
+<1> Normally `test`; usual Maven scoping rules apply.
+
+
+
+== ``SortedSet``s Contract Test
+
+This contract test automatically checks that all fields of type `java.util.Collection` are declared as `java.util.SortedSet`. In other words, it precludes either `java.util.List` or `java.util.Set` from being used as a collection.
+
+For example, the following passes the contract test:
+
+[source,java]
+----
+public class Department {
+    private SortedSet<Employee> employees = new TreeSet<Employee>();
+    ...
+}
+----
+
+whereas this would not:
+
+[source,java]
+----
+public class SomeDomainObject {
+    private List<Employee> employees = new ArrayList<Employee>();
+    ...
+}
+----
+
+If using the JDO/DataNucleus Objectstore then we strongly recommend that you implement this test, for several reasons:
+
+* First, ``Set``s align more closely to the relational model than do `List`s. A `List` must have an additional index to specify order.
+
+* Second, `SortedSet` is preferable to `Set` because then the order is well-defined and predictable (to an end user, to the programmer).
+
+The <<ObjectContracts>> utility class substantially simplifies the task of implementing `Comparable` in your domain classes.
+
+* Third, if the relationship is bidirectional then JDO/Objectstore will automatically maintain the relationship. See link:../components/objectstores/jdo/managed-1-to-m-relationships.html[here] for further discussion.
+
+To use the contract test, subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+[source,java]
+----
+public class SortedSetsContractTestAll extends SortedSetsContractTestAbstract {
+
+    public SortedSetsContractTestAll() {
+        super("org.estatio.dom");
+        withLoggingTo(System.out);
+    }
+}
+----
+
+
+
+
+== Injected Services Method Contract Test
+
+It is quite common for some basic services to be injected in a project-specific domain object superclass; for example a `ClockService` might generally be injected everywhere:
+
+[source,java]
+----
+public abstract class EstatioDomainObject {
+    protected ClockService clockService;
+    public void injectClockService(ClockService clockService) {
+        this.clockService = clockService;
+    }
+}
+----
+
+If a subclass inadvertantly overrides this method and provides its own `ClockService` field, then the field in the superclass will never initialized. As you might imagine, ``NullPointerException``s could then arise.
+
+This contract test automatically checks that the `injectXxx(...)` method, to allow for injected services, is not overridable, ie `final`.
+
+To use the contract test, , subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+[source,java]
+----
+public class InjectServiceMethodMustBeFinalContractTestAll extends InjectServiceMethodMustBeFinalContractTestAbstract {
+
+    public InjectServiceMethodMustBeFinalContractTestAll() {
+        super("org.estatio.dom");
+        withLoggingTo(System.out);
+    }
+}
+----
+
+
+
+
+== Bidirectional Contract Test
+
+This contract test automatically checks that bidirectional 1:m or 1:1 associations are being maintained correctly (assuming that they follow the link:../more-advanced-topics/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html[mutual registration pattern]
+
+TIP: If using the link:../components/objectstores/jdo/about.html[JDO Object Store], then there is generally no need to programmatically maintain 1:m relationships (indeed it may introduce subtle errors). For more details, see link:../components/objectstores/jdo/managed-1-to-m-relationships.html[here]. Check out the link:../intro/resources/editor-templates.html[Eclipse templates] for further guidance.
+
+For example, suppose that `ParentDomainObject` and `ChildDomainObject` have a 1:m relationship (`ParentDomainObject#children` / `ChildDomainObject#parent`), and also `PeerDomainObject` has a 1:1 relationship with itself (`PeerDomainObject#next` / `PeerDomainObject#previous`).
+
+The following will exercise these relationships:
+
+[source,java]
+----
+public class BidirectionalRelationshipContractTestAll
+        extends BidirectionalRelationshipContractTestAbstract {
+
+    public BidirectionalRelationshipContractTestAll() {
+        super("org.apache.isis.core.unittestsupport.bidir",
+                ImmutableMap.<Class<?>,Instantiator>of(
+                    ChildDomainObject.class, new InstantiatorForChildDomainObject(),
+                    PeerDomainObject.class, new InstantiatorSimple(PeerDomainObjectForTesting.class)
+                ));
+        withLoggingTo(System.out);
+    }
+}
+----
+
+The first argument to the constructor scopes the search for domain objects; usually this would be something like `&quot;com.mycompany.dom&quot;`.
+
+The second argument provides a map of `Instantiator` for certain of the domain object types. This has two main purposes. First, for abstract classes, it nominates an alternative concrete class to be instantiated. Second, for classes (such as `ChildDomainObject`) that are `Comparable` and are held in a `SortedSet`), it provides the ability to ensure that different instances are unique when compared against each other. If no `Instantiator` is provided, then the contract test simply attempts to instantiates the class.
+
+If any of the supporting methods (`addToXxx()`, `removeFromXxx()`, `modifyXxx()` or `clearXxx()`) are missing, the relationship is skipped.
+
+To see what's going on (and to identify any skipped relationships), use the `withLoggingTo()` method call. If any assertion fails then the error should be descriptive enough to figure out the problem (without enabling logging).
+
+The example tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/bidir[here].
+
+
+
+
+== JMock Extensions
+
+`JUnitRuleMockery2` is an extension to the JMock's `JunitRuleMockery`, providing a simpler API and also providing support for autowiring.
+
+For example, here we see that the class under test, an instance of `CollaboratingUsingSetterInjection`, is automatically wired up with its `Collaborator`:
+
+[source,java]
+----
+public class JUnitRuleMockery2Test_autoWiring_setterInjection_happyCase {
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+    @Mock
+    private Collaborator collaborator;
+
+    @ClassUnderTest
+    private CollaboratingUsingSetterInjection collaborating;
+
+    @Test
+    public void wiring() {
+        assertThat(collaborating.collaborator, is(not(nullValue())));
+    }
+}
+----
+
+The example tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking[here]
+
+
+
+
+== Value Objects Contract Test
+
+The `ValueTypeContractTestAbstract` automatically tests that a custom value type implements `equals()` and `hashCode()` correctly.
+
+For example, testing JDK's own `java.math.BigInteger` can be done as follows:
+
+[source,java]
+----
+public class ValueTypeContractTestAbstract_BigIntegerTest extends ValueTypeContractTestAbstract<BigInteger> {
+
+    @Override
+    protected List<BigInteger> getObjectsWithSameValue() {
+        return Arrays.asList(new BigInteger("1"), new BigInteger("1"));
+    }
+
+    @Override
+    protected List<BigInteger> getObjectsWithDifferentValue() {
+        return Arrays.asList(new BigInteger("2"));
+    }
+}
+----
+
+The example unit tests can be found https://github.com/apache/isis/tree/master/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/value[here].
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
index d7be033..bc2c280 100644
--- a/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
+++ b/adocs/documentation/src/main/asciidoc/user-guide/user-guide-testing.adoc
@@ -5,70 +5,18 @@
 
 IMPORTANT: TODO
 
-## Unit Test Support
+include::user-guide-testing-unit-test-support.adoc[leveloffset=+1]
 
-## Integration Test Support
+include::user-guide-testing-integ-test-support.adoc[leveloffset=+1]
 
-## BDD/Integ Test Support
+include::user-guide-testing-bdd-integ-test-support.adoc[leveloffset=+1]
 
-## Fixture Scripts
+include::user-guide-testing-fixture-scripts.adoc[leveloffset=+1]
 
-## SudoService (1.9.0-SNAPSHOT)
+include::user-guide-testing-fake-data.adoc[leveloffset=+1]
 
-Sometimes in our fixture scripts we want to perform a business action runnin as a particular user.  This might be for the usual reason - so that our fixtures accurately reflect the reality of the system with all business constraints enforced using the `WrapperFactory` - or more straightforwardly it might be simply that the action depends on the identity of the user invoking the action.
 
-An example of the latter case is in the link:[todoapp]'s `ToDoItem` class:
 
-[source,java]
-.Production code that depends on current user
-----
-public ToDoItem newToDo(
-        @Parameter(regexPattern = "\\w[@&:\\-\\,\\.\\+ \\w]*") @ParameterLayout(named="Description")
-        final String description,
-        @ParameterLayout(named="Category")
-        final Category category,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Subcategory")
-        final Subcategory subcategory,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Due by")
-        final LocalDate dueBy,
-        @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named="Cost")
-        final BigDecimal cost) {
-    return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
-}
-private String currentUserName() {
-    return container.getUser().getName(); // <1>
-}
-----
-<1> is the current user.
 
-The fixture for this can use the `SudoService` to run a block of code as a specified user:
-
-[source,java]
-.Fixture Script
-----
-final String description = ...
-final Category category = ...
-final Subcategory subcategory = ...
-final LocalDate dueBy = ...
-final BigDecimal cost = ...
-final Location location = ...
-
-toDoItem = sudoService.sudo(username,
-        new Callable<ToDoItem>() {
-            @Override
-            public ToDoItem call() {
-                final ToDoItem toDoItem = wrap(toDoItems).newToDo(
-                        description, category, subcategory, dueBy, cost);
-                wrap(toDoItem).setLocation(location);
-                return toDoItem;
-            }
-        });
-----
-
-Behind the scenes the `SudoService` simply talks to the `DomainObjectContainer` to override the user returned by the `getUser()` API.  It is possible to override both users and roles.
-
-## IsisConfigurationForJdoIntegTests
-
-## Isis CmdLine Arguments (for prototyping)
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/5e33aa8e/adocs/template/document.html.erb
----------------------------------------------------------------------
diff --git a/adocs/template/document.html.erb b/adocs/template/document.html.erb
index 2986460..6106875 100644
--- a/adocs/template/document.html.erb
+++ b/adocs/template/document.html.erb
@@ -108,6 +108,19 @@
         }
     </style>
 
+    <style>
+        /* overriding colony.css stylesheet */
+        .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] {
+           /*padding: 1.25em 1.5625em 1.125em 1.5625em;*/
+           padding: 0.3em 0.6em 0.25em 0.6em;
+        }
+        @media only screen and (min-width: 1280px)
+        #toc.toc2 {
+          /*width: 20em;*/
+          width: 25em;
+        }
+    </style>
+
 </head>
 <body>
 
@@ -214,7 +227,7 @@
 </div>
 
 <div class="row">
-    <div class="large-9 medium-9 columns">
+    <div class="large-12 medium-12 columns">
 
         <div id="doc-content">
           <%= document.content %>
@@ -231,11 +244,16 @@
 
     </div>
 
-    <div class="large-3 medium-3 columns">
+    <!--
+    as a column to the right
+    (previous was using foundation in a 9:3 ratio with the content, above... decided was too crammed.
+    -->
+    <div class="xlarge-3 xmedium-3 xcolumns">
         <div id="toc" class="<%= attr 'toc-class', 'toc2' %>">
           <%= converter.convert_with_options @document, 'outline', :toclevels => 6  %>
         </div>
     </div>
+
 </div>