You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/11/30 23:05:25 UTC

[2/3] incubator-brooklyn git commit: Code review comments from https://github.com/apache/incubator-brooklyn/pull/1066/.

Code review comments from https://github.com/apache/incubator-brooklyn/pull/1066/.

Unused Imports
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45793815
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45934555

Use 'Suppliers.ofInstance' where appropriate.
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45842448

Add member variable for default exit code assertion.
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45933970
Note the logic has been corrected, the default exit status assertion
is meant to be made only if you don't supply any assertions.  If you
supply for example just an assertion on stdout then this should mean
you don't care what the exit code is.

Throw exception instead of reporting inaccurate status code.
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45843346

Make the assertions tolerant to definition as maps or as lists of maps
https://github.com/apache/incubator-brooklyn/pull/1066/files#r45842311

Also:

remove some redundant duplicated declarations (EQUALS...)


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/e1412e80
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/e1412e80
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/e1412e80

Branch: refs/heads/master
Commit: e1412e8078c76710f3aedd47191783ab77160553
Parents: d3d120c
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Thu Nov 26 11:23:30 2015 +0000
Committer: Geoff Macartney <ge...@cloudsoftcorp.com>
Committed: Thu Nov 26 13:07:27 2015 +0000

----------------------------------------------------------------------
 .../brooklyn/test/framework/BaseTest.java       | 12 ++---
 .../test/framework/SimpleShellCommandTest.java  | 47 ++++++++------------
 .../framework/SimpleShellCommandTestImpl.java   | 31 ++++++-------
 .../test/framework/TestFrameworkAssertions.java | 44 ++++++++++++++++++
 .../test/framework/TestHttpCallImpl.java        | 10 ++---
 .../brooklyn/test/framework/TestSensorImpl.java |  4 +-
 .../SimpleShellCommandIntegrationTest.java      |  3 +-
 .../framework/TestFrameworkAssertionsTest.java  |  1 -
 .../test/framework/TestHttpCallTest.java        |  2 +-
 .../brooklyn/test/framework/TestSensorTest.java | 32 +++++++------
 .../testhttpcall-examples.yml                   | 17 ++++---
 11 files changed, 120 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
index 19043e7..d316268 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/BaseTest.java
@@ -47,16 +47,16 @@ public interface BaseTest extends Entity, Startable {
     ConfigKey<String> TARGET_ID = ConfigKeys.newStringConfigKey("targetId", "Id of the entity under test");
 
     /**
-     * The assertions to be made
+     * The assertions to be made.
      */
-    ConfigKey<List<Map<String, Object>>> ASSERTIONS = ConfigKeys.newConfigKey(
-            new TypeToken<List<Map<String, Object>>>() {},
-            "assert", "Assertions to be evaluated", new ArrayList<Map<String, Object>>());
+    ConfigKey<Object> ASSERTIONS = ConfigKeys.newConfigKey(Object.class, "assert", "Assertions to be evaluated",
+        new ArrayList<Map<String, Object>>());
 
     /**
-     * THe duration to wait
+     * THe duration to wait for an assertion to succeed or fail before throwing an exception.
      */
-    ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout", "Time to wait on result", new Duration(1L, TimeUnit.SECONDS));
+    ConfigKey<Duration> TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "timeout", "Time to wait on result",
+        new Duration(1L, TimeUnit.SECONDS));
 
     /**
      * Get the target of the test.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java
index de1f176..4fb2def 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTest.java
@@ -18,7 +18,8 @@
  */
 package org.apache.brooklyn.test.framework;
 
-import com.google.common.collect.Maps;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.reflect.TypeToken;
 import org.apache.brooklyn.api.entity.ImplementedBy;
 import org.apache.brooklyn.config.ConfigKey;
@@ -39,27 +40,10 @@ import static org.apache.brooklyn.core.config.ConfigKeys.newConfigKey;
 @ImplementedBy(SimpleShellCommandTestImpl.class)
 public interface SimpleShellCommandTest extends BaseTest {
 
-    String TMP_DEFAULT = "/tmp";
-
-    /**
-     * Equals assertion on command result.
-     */
-    String EQUALS = "equals";
-
     /**
-     * String contains assertion on command result.
+     * Default location for temporary files.
      */
-    String CONTAINS = "contains";
-
-    /**
-     * Regex match assertion on command result.
-     */
-    String MATCHES = "matches";
-
-    /**
-     * Is-empty match assertion on command result.
-     */
-    String IS_EMPTY = "isEmpty";
+    String TMP_DEFAULT = "/tmp";
 
     /**
      * Supply the command to invoke directly. Cannot be used together with {@link #DOWNLOAD_URL}.
@@ -84,30 +68,35 @@ public interface SimpleShellCommandTest extends BaseTest {
      */
     @SetFromFlag("runDir")
     ConfigKey<String> RUN_DIR = newConfigKey(String.class, "run.dir", "directory where downloaded scripts should be run from");
+
+
+    /**
+     * If no assertions are configured in the test then the default is this assertion that exit status of the command
+     * is zero (successful).
+     */
+    Map<String, Object> DEFAULT_ASSERTION = ImmutableMap.<String,Object>of(TestFrameworkAssertions.EQUALS, 0);
+
     /**
      * Assertions on the exit code of the simple command.
      *
      * If not explicitly configured, the default assertion is a non-zero exit code.
      */
     @SetFromFlag("assertStatus")
-    ConfigKey<List<Map<String, Object>>> ASSERT_STATUS = ConfigKeys.newConfigKey(
-        new TypeToken<List<Map<String, Object>>>() {},
-        "assert.status", "Assertions on command exit code", new ArrayList<Map<String, Object>>());
+    ConfigKey<Object> ASSERT_STATUS = ConfigKeys.newConfigKey(Object.class, "assert.status", "Assertions on command exit code",
+        new ArrayList<Map<String, Object>>());
 
     /**
      * Assertions on the standard output of the command as a String.
      */
     @SetFromFlag("assertOut")
-    ConfigKey<List<Map<String, Object>>> ASSERT_OUT = ConfigKeys.newConfigKey(
-        new TypeToken<List<Map<String, Object>>>() {},
-        "assert.out", "Assertions on command standard output", new ArrayList<Map<String, Object>>());
+    ConfigKey<Object> ASSERT_OUT = ConfigKeys.newConfigKey(Object.class, "assert.out", "Assertions on command standard output",
+        new ArrayList<Map<String, Object>>());
 
     /**
      * Assertions on the standard error of the command as a String.
      */
     @SetFromFlag("assertErr")
-    ConfigKey<List<Map<String, Object>>> ASSERT_ERR = ConfigKeys.newConfigKey(
-        new TypeToken<List<Map<String, Object>>>() {},
-        "assert.err", "Assertions on command standard error", new ArrayList<Map<String, Object>>());
+    ConfigKey<Object> ASSERT_ERR = ConfigKeys.newConfigKey(Object.class, "assert.err", "Assertions on command standard error",
+        new ArrayList<Map<String, Object>>());
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java
index 5a709e8..e01c482 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/SimpleShellCommandTestImpl.java
@@ -21,10 +21,11 @@ package org.apache.brooklyn.test.framework;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
-import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableMap;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.mgmt.TaskFactory;
+import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
 import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
 import org.apache.brooklyn.core.location.Machines;
@@ -47,14 +48,14 @@ import java.util.*;
 
 import static org.apache.brooklyn.core.entity.lifecycle.Lifecycle.*;
 import static org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.setExpectedState;
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.checkAssertions;
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.getAssertions;
 import static org.apache.brooklyn.util.text.Strings.isBlank;
 import static org.apache.brooklyn.util.text.Strings.isNonBlank;
 
 // TODO assertions below should use TestFrameworkAssertions but that class needs to be improved to give better error messages
 public class SimpleShellCommandTestImpl extends AbstractTest implements SimpleShellCommandTest {
 
-    public static final int SUCCESS = 0;
-
     private static final Logger LOG = LoggerFactory.getLogger(SimpleShellCommandTestImpl.class);
     private static final int A_LINE = 80;
     public static final String DEFAULT_NAME = "download.sh";
@@ -109,21 +110,12 @@ public class SimpleShellCommandTestImpl extends AbstractTest implements SimpleSh
         });
         ImmutableMap<String, Duration> flags = ImmutableMap.of("timeout", getConfig(TIMEOUT));
         AssertionSupport support = new AssertionSupport();
-        TestFrameworkAssertions.checkAssertions(support, flags, exitCodeAssertions(), "exit code", supply(result.getExitCode()));
-        TestFrameworkAssertions.checkAssertions(support, flags, getConfig(ASSERT_OUT), "stdout", supply(result.getStdout()));
-        TestFrameworkAssertions.checkAssertions(support, flags, getConfig(ASSERT_ERR), "stderr", supply(result.getStderr()));
+        checkAssertions(support, flags, exitCodeAssertions(), "exit code", Suppliers.ofInstance(result.getExitCode()));
+        checkAssertions(support, flags, getAssertions(this, ASSERT_OUT), "stdout", Suppliers.ofInstance(result.getStdout()));
+        checkAssertions(support, flags, getAssertions(this, ASSERT_ERR), "stderr", Suppliers.ofInstance(result.getStderr()));
         support.validate();
     }
 
-    private static <T> Supplier<T> supply(final T t) {
-        return new Supplier<T>() {
-            @Override
-            public T get() {
-                return t;
-            }
-        };
-    }
-
     private String shorten(String text) {
         return Strings.maxlenWithEllipsis(text, A_LINE);
     }
@@ -240,9 +232,12 @@ public class SimpleShellCommandTestImpl extends AbstractTest implements SimpleSh
     
 
     private List<Map<String, Object>> exitCodeAssertions() {
-        List<Map<String, Object>> assertStatus = getConfig(ASSERT_STATUS);
-        if (assertStatus.isEmpty()) {
-            Map<String, Object> shouldSucceed = ImmutableMap.<String,Object>of(EQUALS, SUCCESS);
+        List<Map<String, Object>> assertStatus = getAssertions(this, ASSERT_STATUS);
+        List<Map<String, Object>> assertOut = getAssertions(this, ASSERT_OUT);
+        List<Map<String, Object>> assertErr = getAssertions(this, ASSERT_ERR);
+
+        if (assertStatus.isEmpty() && assertOut.isEmpty() && assertErr.isEmpty()) {
+            Map<String, Object> shouldSucceed = DEFAULT_ASSERTION;
             assertStatus.add(shouldSucceed);
         }
         return assertStatus;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
index bd955fa..fee68e6 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestFrameworkAssertions.java
@@ -20,11 +20,18 @@ package org.apache.brooklyn.test.framework;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Supplier;
+import com.google.common.reflect.TypeToken;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
+import org.apache.brooklyn.util.exceptions.FatalConfigurationRuntimeException;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -52,6 +59,43 @@ public class TestFrameworkAssertions {
     private TestFrameworkAssertions() {
     }
 
+
+    /**
+     *  Get assertions tolerantly from a configuration key.
+     *  This supports either a simple map of assertions, such as
+     *
+     <pre>
+     assertOut:
+       contains: 2 users
+       matches: .*[\d]* days.*
+     </pre>
+     * or a list of such maps, (which allows you to repeat keys):
+     <pre>
+     assertOut:
+     - contains: 2 users
+     - contains: 2 days
+     </pre>
+     or
+    private static List<Map<String,Object>> getAssertions(ConfigKey<Object> key) {
+    }
+    */
+    public static List<Map<String, Object>> getAssertions(Entity entity, ConfigKey<Object> key) {
+        Object config = entity.getConfig(key);
+        Maybe<Map<String, Object>> maybeMap = TypeCoercions.tryCoerce(config, new TypeToken<Map<String, Object>>() {});
+        if (maybeMap.isPresent()) {
+            return Collections.singletonList(maybeMap.get());
+        }
+
+        Maybe<List<Map<String, Object>>> maybeList = TypeCoercions.tryCoerce(config,
+            new TypeToken<List<Map<String, Object>>>() {});
+        if (maybeList.isPresent()) {
+            return maybeList.get();
+        }
+
+        throw new FatalConfigurationRuntimeException(key.getDescription() + " is not a map or list of maps");
+    }
+
+
     public static <T> void checkAssertions(Map<String,?> flags,
                                            Map<String, Object> assertions,
                                            String target,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
index 92f2885..67451ed 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
@@ -27,7 +27,6 @@ import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.http.HttpTool;
 import org.apache.brooklyn.util.time.Duration;
-import org.apache.http.HttpStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,6 +34,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.getAssertions;
+
 /**
  * {@inheritDoc}
  */
@@ -51,7 +52,7 @@ public class TestHttpCallImpl extends AbstractTest implements TestHttpCall {
         }
         ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING);
         final String url = getConfig(TARGET_URL);
-        final List<Map<String, Object>> assertions = getConfig(ASSERTIONS);
+        final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS);
         final Duration timeout = getConfig(TIMEOUT);
         final HttpAssertionTarget target = getConfig(ASSERTION_TARGET);
 
@@ -87,9 +88,8 @@ public class TestHttpCallImpl extends AbstractTest implements TestHttpCall {
                         try {
                             return HttpTool.getHttpStatusCode(url);
                         } catch (Exception e) {
-                            LOG.error("HTTP call to [{}] failed due to [{}] ... returning Status code [500]",
-                                url, e.getMessage());
-                            return HttpStatus.SC_INTERNAL_SERVER_ERROR;
+                            LOG.info("HTTP call to [{}] failed due to [{}]", url, e.getMessage());
+                            throw Exceptions.propagate(e);
                         }
                     }
                 };

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
index f5ed913..f368cf5 100644
--- a/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
+++ b/usage/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSensorImpl.java
@@ -38,6 +38,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.getAssertions;
+
 /**
  * {@inheritDoc}
  */
@@ -56,7 +58,7 @@ public class TestSensorImpl extends AbstractTest implements TestSensor {
         final Entity target = resolveTarget();
         final String sensor = getConfig(SENSOR_NAME);
         final Duration timeout = getConfig(TIMEOUT);
-        final List<Map<String, Object>> assertions = getConfig(ASSERTIONS);
+        final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS);
         try {
             TestFrameworkAssertions.checkAssertions(ImmutableMap.of("timeout", timeout), assertions, sensor,
                 new Supplier<Object>() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java
index 9e6a27a..9a3b339 100644
--- a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java
+++ b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/SimpleShellCommandIntegrationTest.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.test.framework;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
 import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
@@ -44,6 +43,8 @@ import java.util.Map;
 
 import static org.apache.brooklyn.test.framework.BaseTest.TARGET_ENTITY;
 import static org.apache.brooklyn.test.framework.SimpleShellCommandTest.*;
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.CONTAINS;
+import static org.apache.brooklyn.test.framework.TestFrameworkAssertions.EQUALS;
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class SimpleShellCommandIntegrationTest extends BrooklynAppUnitTestSupport {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
index 60d452c..482cf5e 100644
--- a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
+++ b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestFrameworkAssertionsTest.java
@@ -35,7 +35,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
-import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * @author m4rkmckenna on 11/11/2015.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
index f3552e6..055c5fa 100644
--- a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
+++ b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
@@ -50,7 +50,7 @@ public class TestHttpCallTest {
     private LocalhostMachineProvisioningLocation loc;
     private String testId;
 
-    @BeforeMethod
+    @BeforeMethod(alwaysRun = true)
     public void setup() {
         testId = Identifiers.makeRandomId(8);
         server = new TestHttpServer()

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
index 9fea7a5..4a00d75 100644
--- a/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
+++ b/usage/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestSensorTest.java
@@ -80,17 +80,17 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("equals", true)));
+                .configure(TestSensor.ASSERTIONS, newMapAssertion("equals", true)));
         //Add Sensor Test for STRING sensor
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("equals", testId)));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("equals", testId)));
         //Add Sensor Test for INTEGER sensor
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, INTEGER_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("equals", testInteger)));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("equals", testInteger)));
 
         //Set BOOLEAN Sensor to true
         app.sensors().set(BOOLEAN_SENSOR, Boolean.TRUE);
@@ -113,7 +113,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("equals", true)));
+                .configure(TestSensor.ASSERTIONS, newMapAssertion("equals", true)));
 
         //Set BOOLEAN Sensor to false
         app.sensors().set(BOOLEAN_SENSOR, Boolean.FALSE);
@@ -137,7 +137,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("equals", false)));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("equals", false)));
 
         try {
             app.start(ImmutableList.of(loc));
@@ -156,12 +156,12 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS,  newAssertion("isNull", true)));
+                .configure(TestSensor.ASSERTIONS,  newMapAssertion("isNull", true)));
         //Add Sensor Test for STRING sensor
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("notNull", true)));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("notNull", true)));
 
         //Set STRING sensor to random string
         app.sensors().set(STRING_SENSOR, testId);
@@ -178,7 +178,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("isNull", true)));
+                .configure(TestSensor.ASSERTIONS, newMapAssertion("isNull", true)));
 
         //Set STRING sensor to random string
         app.sensors().set(STRING_SENSOR, testId);
@@ -205,11 +205,11 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("matches", String.format(".*%s.*", time))));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("matches", String.format(".*%s.*", time))));
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, BOOLEAN_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("matches", "true")));
+                .configure(TestSensor.ASSERTIONS, newMapAssertion("matches", "true")));
 
         //Set STRING sensor
         app.sensors().set(STRING_SENSOR, sensorValue);
@@ -228,7 +228,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("matches", String.format(".*%s.*", Identifiers.makeRandomId(8)))));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("matches", String.format(".*%s.*", Identifiers.makeRandomId(8)))));
 
         //Set STRING sensor
         app.sensors().set(STRING_SENSOR, sensorValue);
@@ -250,7 +250,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, STRING_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("matches", String.format(".*%s.*", Identifiers.makeRandomId(8)))));
+                .configure(TestSensor.ASSERTIONS, newMapAssertion("matches", String.format(".*%s.*", Identifiers.makeRandomId(8)))));
 
         try {
             app.start(ImmutableList.of(loc));
@@ -270,7 +270,7 @@ public class TestSensorTest {
         app.createAndManageChild(EntitySpec.create(TestSensor.class)
                 .configure(TestSensor.TARGET_ENTITY, app)
                 .configure(TestSensor.SENSOR_NAME, OBJECT_SENSOR.getName())
-                .configure(TestSensor.ASSERTIONS, newAssertion("matches", ".*TestObject.*id=.*")));
+                .configure(TestSensor.ASSERTIONS, newListAssertion("matches", ".*TestObject.*id=.*")));
 
         app.sensors().set(OBJECT_SENSOR, new TestObject());
 
@@ -278,12 +278,16 @@ public class TestSensorTest {
 
     }
 
-    private List<Map<String, Object>> newAssertion(final String assertionKey, final Object assertionValue) {
+    private List<Map<String, Object>> newListAssertion(final String assertionKey, final Object assertionValue) {
         final List<Map<String, Object>> result = new ArrayList<>();
         result.add(ImmutableMap.<String, Object>of(assertionKey, assertionValue));
         return result;
     }
 
+    private Map<String, Object> newMapAssertion(final String assertionKey, final Object assertionValue) {
+        return ImmutableMap.<String, Object>of(assertionKey, assertionValue);
+    }
+
 
     class TestObject {
         private final String id;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e1412e80/usage/test-framework/src/test/resources/test-framework-examples/testhttpcall-examples.yml
----------------------------------------------------------------------
diff --git a/usage/test-framework/src/test/resources/test-framework-examples/testhttpcall-examples.yml b/usage/test-framework/src/test/resources/test-framework-examples/testhttpcall-examples.yml
index 9844d20..6885679 100644
--- a/usage/test-framework/src/test/resources/test-framework-examples/testhttpcall-examples.yml
+++ b/usage/test-framework/src/test/resources/test-framework-examples/testhttpcall-examples.yml
@@ -31,20 +31,23 @@ services:
     url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
     applyAssertionTo: status
     assert:
-      - equalTo: 200
+      equalTo: 200
   - type: org.apache.brooklyn.test.framework.TestHttpCall
     name: Status Code 404
     url: $brooklyn:formatString("%s/invalidpath/", component("tomcat").attributeWhenReady("webapp.url"))
     timeout: 10s
     applyAssertionTo: status
     assert:
-      - equals: 404
+      equals: 404
   - type: org.apache.brooklyn.test.framework.TestHttpCall
     name: String match
     url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
     applyAssertionTo: body
+     # This example illustrates the use of a list of maps in order to repeat a key multiple times.
     assert:
-      - contains: Sample Brooklyn Deployed
+      - contains: Sample
+      - contains: Brooklyn
+      - contains: Deployed
   - type: org.apache.brooklyn.test.framework.TestHttpCall
     name: Regex match
     url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
@@ -53,7 +56,7 @@ services:
     # a multi-line response you should use the embedded dotall flag expression `(?s)` in your regex.
     # See: http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
     assert:
-      - matches: "(?s).*illustrate(\\s)*how(\\s)*web(\\s)*applications.*"
+      matches: "(?s).*illustrate(\\s)*how(\\s)*web(\\s)*applications.*"
 
 ...
 
@@ -72,13 +75,13 @@ services:
     url: $brooklyn:component("tomcat").attributeWhenReady("webapp.url")
     applyAssertionTo: status
     assert:
-    - isEqualTo: 200
+      isEqualTo: 200
   - type: org.apache.brooklyn.test.framework.TestHttpCall
     name: /newcontext Status Code 404
     url: $brooklyn:formatString("%s/newcontext/", component("tomcat").attributeWhenReady("webapp.url"))
     applyAssertionTo: status
     assert:
-    - equalTo: 404
+      equalTo: 404
   - type: org.apache.brooklyn.test.framework.TestEffector
     name: Deploy WAR in /newcontext
     target: $brooklyn:component("tomcat")
@@ -93,7 +96,7 @@ services:
     timeout: 10s
     applyAssertionTo: status
     assert:
-    - equals: 200
+      equals: 200
 ...
 
 ---