You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/04 21:51:59 UTC

[2/4] incubator-brooklyn git commit: brooklyn-utils-test-support: add org.apache package prefix

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e06e79ab/utils/test-support/src/main/java/org/apache/brooklyn/test/PlatformTestSelectorListener.java
----------------------------------------------------------------------
diff --git a/utils/test-support/src/main/java/org/apache/brooklyn/test/PlatformTestSelectorListener.java b/utils/test-support/src/main/java/org/apache/brooklyn/test/PlatformTestSelectorListener.java
new file mode 100644
index 0000000..0282eee
--- /dev/null
+++ b/utils/test-support/src/main/java/org/apache/brooklyn/test/PlatformTestSelectorListener.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.brooklyn.test;
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.ITestResult;
+import org.testng.SkipException;
+
+public class PlatformTestSelectorListener implements IInvokedMethodListener {
+    private static final String GROUP_UNIX = "UNIX";
+    private static final String GROUP_WINDOWS = "Windows";
+
+    public static boolean isWindows() {
+        return System.getProperty("os.name").startsWith("Windows");
+    }
+
+    @Override
+    public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
+        boolean isUnixTest = false;
+        boolean isWinTest = false;
+        
+        String[] groups = method.getTestMethod().getGroups();
+        for (String group : groups) {
+            isUnixTest = isUnixTest || group.equalsIgnoreCase(GROUP_UNIX);
+            isWinTest = isWinTest || group.equalsIgnoreCase(GROUP_WINDOWS);
+        }
+        
+        boolean isWinPlatform = isWindows();
+        if (isUnixTest || isWinTest) {
+            if (isWinPlatform && isUnixTest && !isWinTest) {
+                throw new SkipException("Skipping unix-specific test."); 
+            } else if (!isWinPlatform && isWinTest && !isUnixTest) {
+                throw new SkipException("Skipping windows-specific test."); 
+            }
+        }
+    }
+
+    @Override
+    public void afterInvocation(IInvokedMethod method, ITestResult testResult) {}
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e06e79ab/utils/test-support/src/main/java/org/apache/brooklyn/test/StatusListener.java
----------------------------------------------------------------------
diff --git a/utils/test-support/src/main/java/org/apache/brooklyn/test/StatusListener.java b/utils/test-support/src/main/java/org/apache/brooklyn/test/StatusListener.java
new file mode 100644
index 0000000..1803967
--- /dev/null
+++ b/utils/test-support/src/main/java/org/apache/brooklyn/test/StatusListener.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+package org.apache.brooklyn.test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.IClass;
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+/**
+ * adapted from the following class:
+ * 
+ * @see org.jclouds.test.testng.UnitTestStatusListener
+ * 
+ * normally not used, preferring instead LoggingVerboseReporter which prints out config info
+ */
+public class StatusListener implements ITestListener {
+    
+    public static final Logger log = LoggerFactory.getLogger(StatusListener.class);
+    
+    /**
+     * Holds test classes actually running in all threads.
+     */
+    private ThreadLocal<IClass> threadTestClass = new ThreadLocal<IClass>();
+    private ThreadLocal<Long> threadTestStart = new ThreadLocal<Long>();
+
+    private AtomicInteger failed = new AtomicInteger(0);
+    private AtomicInteger succeded = new AtomicInteger(0);
+    private AtomicInteger skipped = new AtomicInteger(0);
+
+    //TODO instead of system.out.println we should log -- *and* perhaps write to sysout if logger doesn't?
+    protected static void log(String msg) {
+        log.info(msg);
+    }
+    
+    public void onTestStart(ITestResult res) {
+        log("Starting test " + getTestDesc(res));
+        threadTestClass.set(res.getTestClass());
+        threadTestStart.set(System.currentTimeMillis());
+    }
+
+    synchronized public void onTestSuccess(ITestResult arg0) {
+        log(getThreadId() + " Test " + getTestDesc(arg0) + " succeeded: " + (System.currentTimeMillis() - threadTestStart.get()) + "ms");
+        succeded.incrementAndGet();
+        printStatus();
+    }
+
+    synchronized public void onTestFailure(ITestResult arg0) {
+        log(getThreadId() + " Test " + getTestDesc(arg0) + " failed: "+arg0.getThrowable());
+        failed.incrementAndGet();
+        printStatus();
+    }
+
+    synchronized public void onTestSkipped(ITestResult arg0) {
+        System.out.println(getThreadId() + " Test " + getTestDesc(arg0) + " skipped.");
+        skipped.incrementAndGet();
+        printStatus();
+    }
+
+    public void onTestFailedButWithinSuccessPercentage(ITestResult arg0) {
+    }
+
+    public void onStart(ITestContext arg0) {
+    }
+
+    public void onFinish(ITestContext arg0) {
+    }
+
+    private String getThreadId() {
+        return "[" + Thread.currentThread().getName() + "]";
+    }
+
+    private String getTestDesc(ITestResult res) {
+        return res.getMethod().getMethodName() + "(" + res.getTestClass().getName() + ")";
+    }
+
+    private void printStatus() {
+        log("Test suite progress: tests succeeded: " + succeded.get() + ", failed: " + failed.get() + ", skipped: " + skipped.get() + ".");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e06e79ab/utils/test-support/src/main/java/org/apache/brooklyn/test/TestResourceUnavailableException.java
----------------------------------------------------------------------
diff --git a/utils/test-support/src/main/java/org/apache/brooklyn/test/TestResourceUnavailableException.java b/utils/test-support/src/main/java/org/apache/brooklyn/test/TestResourceUnavailableException.java
new file mode 100644
index 0000000..c49a248
--- /dev/null
+++ b/utils/test-support/src/main/java/org/apache/brooklyn/test/TestResourceUnavailableException.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+package org.apache.brooklyn.test;
+
+import com.google.common.base.Throwables;
+import org.testng.SkipException;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Indicates that a test cannot be run as a necessary resource is not available.
+ *
+ * <p>This exception should be used by tests that need a particular test resource (i.e., a file that is conventionally
+ * in the <code>src/test/resources</code> folder, and that available as a classpath resource at runtime) is not
+ * available. It will cause TestNG to mark the test as "skipped" with a suitable message.</p>
+ *
+ * <p>Some tests require binary files (such as OSGi bundles) which under Apache conventions are not able to be
+ * distributed in our source code release. This exception allows such tests to become "optional" so that they do not
+ * cause test failures when running the tests on a source distribution.</p>
+ *
+ * <p>Note that the single-string constructors expect the string to be the simple name of the classpath resource that
+ * is not available. The exception message is then derived from this. The two-string constructors take both the
+ * resource name and an explicit exception message.</p>
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class TestResourceUnavailableException extends SkipException {
+
+    private final String resourceName;
+
+    /**
+     * Asserts that a resource is available on the classpath; otherwise, throws {@link TestResourceUnavailableException}
+     *
+     * Note that this will use the same classloader that was used to load this class.
+     *
+     * @param resourceName the classpath resource name, e.g.
+     *                     <code>/brooklyn/osgi/brooklyn-test-osgi-entities.jar</code>
+     */
+    public static void throwIfResourceUnavailable(Class<?> relativeToClass, String resourceName) {
+        checkNotNull(relativeToClass, relativeToClass);
+        checkNotNull(resourceName, "resourceName");
+        checkArgument(!resourceName.isEmpty(), "resourceName must not be empty");
+        InputStream resource = relativeToClass.getResourceAsStream(resourceName);
+        if (resource == null)
+            throw new TestResourceUnavailableException(resourceName);
+
+        // just make sure we clean up the resource
+        try {
+            resource.close();
+        } catch (IOException e) {
+            Throwables.propagate(e);
+        }
+    }
+
+    /**
+     * Instantiate an exception, giving the name of the unavailable resource.
+     *
+     * @param resourceName the name of the resource on the classpath, e.g.
+     *                     <code>/brooklyn/osgi/brooklyn-test-osgi-entities.jar</code>
+     */
+    public TestResourceUnavailableException(String resourceName) {
+        super(messageFromResourceName(resourceName));
+        this.resourceName = resourceName;
+    }
+
+    /**
+     * Instantiate an exception, giving the name of the unavailable resource.
+     *
+     * @param resourceName the name of the resource on the classpath, e.g.
+     *                     <code>/brooklyn/osgi/brooklyn-test-osgi-entities.jar</code>
+     * @param cause the underlying exception that caused this one
+     */
+    public TestResourceUnavailableException(String resourceName, Throwable cause) {
+        super(messageFromResourceName(resourceName), cause);
+        this.resourceName = resourceName;
+    }
+
+    /**
+     * Instantiate an exception, giving the name of the unavailable resource.
+     *
+     * @param resourceName the name of the resource on the classpath, e.g.
+     *                     <code>/brooklyn/osgi/brooklyn-test-osgi-entities.jar</code>
+     * @param skipMessage the message associated with the exception
+     */
+    public TestResourceUnavailableException(String resourceName, String skipMessage) {
+        super(skipMessage);
+        this.resourceName = resourceName;
+    }
+
+    /**
+     * Instantiate an exception, giving the name of the unavailable resource.
+     *
+     * @param resourceName the name of the resource on the classpath, e.g.
+     *                     <code>/brooklyn/osgi/brooklyn-test-osgi-entities.jar</code>
+     * @param skipMessage the message associated with the exception
+     * @param cause the underlying exception that caused this one
+     */
+    public TestResourceUnavailableException(String resourceName, String skipMessage, Throwable cause) {
+        super(skipMessage, cause);
+        this.resourceName = resourceName;
+    }
+
+    private static String messageFromResourceName(String resourceName) {
+        return String.format("Test resource '%s' not found; test skipped.", resourceName);
+    }
+
+    /**
+     * Get the name of the classpath resource that could not be loaded.
+     *
+     * @return the name of the classpath resource whose absence caused this exception.
+     */
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    @Override
+    public boolean isSkip() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e06e79ab/utils/test-support/src/main/java/org/apache/brooklyn/test/VerboseReporter.java
----------------------------------------------------------------------
diff --git a/utils/test-support/src/main/java/org/apache/brooklyn/test/VerboseReporter.java b/utils/test-support/src/main/java/org/apache/brooklyn/test/VerboseReporter.java
new file mode 100644
index 0000000..0ec78e1
--- /dev/null
+++ b/utils/test-support/src/main/java/org/apache/brooklyn/test/VerboseReporter.java
@@ -0,0 +1,343 @@
+/*
+ * 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.
+ */
+package org.apache.brooklyn.test;
+
+import java.util.List;
+
+import org.testng.ITestContext;
+import org.testng.ITestNGMethod;
+import org.testng.ITestResult;
+import org.testng.TestListenerAdapter;
+import org.testng.internal.ConstructorOrMethod;
+import org.testng.internal.Utils;
+
+/**
+ * Reporter printing out detailed messages about what TestNG
+ * is going to run and what is the status of what has been just run.
+ *
+ * To see messages from this reporter, either run Ant in verbose mode ('ant -v')
+ * or set verbose level to 5 or higher
+ *
+ * @author Lukas Jungmann
+ * @since 6.4
+ * 
+ * THIS IS AN EXACT COPY OF THE CLASS IN org.testng.reporters
+ * EXCEPT FOR THIS COMMENT AND log(String) CHANGED TO BE PROTECTED
+ */
+public class VerboseReporter extends TestListenerAdapter {
+
+    /**
+     * Default prefix for messages printed out by this reporter
+     *
+     */
+    public static final String LISTENER_PREFIX = "[VerboseTestNG] ";
+    private String suiteName;
+    private final String prefix;
+
+    private enum Status {
+
+        SUCCESS(ITestResult.SUCCESS), FAILURE(ITestResult.FAILURE), SKIP(ITestResult.SKIP),
+        SUCCESS_PERCENTAGE_FAILURE(ITestResult.SUCCESS_PERCENTAGE_FAILURE), STARTED(ITestResult.STARTED);
+        private final int code;
+
+        private Status(int i) {
+            code = i;
+        }
+        
+        @SuppressWarnings("unused")
+        public int getCode() {
+            return code;
+        }
+    }
+
+    /**
+     * Default constructor
+     */
+    public VerboseReporter() {
+        this(LISTENER_PREFIX);
+    }
+
+    /**
+     * Create VerboseReporter with custom prefix
+     *
+     * @param prefix prefix for messages printed out by this reporter
+     */
+    public VerboseReporter(String prefix) {
+        this.prefix = prefix;
+    }
+
+    @Override
+    public void beforeConfiguration(ITestResult tr) {
+        super.beforeConfiguration(tr);
+        logTestResult(Status.STARTED, tr, true);
+    }
+
+    @Override
+    public void onConfigurationFailure(ITestResult tr) {
+        super.onConfigurationFailure(tr);
+        logTestResult(Status.FAILURE, tr, true);
+    }
+
+    @Override
+    public void onConfigurationSkip(ITestResult tr) {
+        super.onConfigurationSkip(tr);
+        logTestResult(Status.SKIP, tr, true);
+    }
+
+    @Override
+    public void onConfigurationSuccess(ITestResult tr) {
+        super.onConfigurationSuccess(tr);
+        logTestResult(Status.SUCCESS, tr, true);
+    }
+
+    @Override
+    public void onTestStart(ITestResult tr) {
+        logTestResult(Status.STARTED, tr, false);
+    }
+
+    @Override
+    public void onTestFailure(ITestResult tr) {
+        super.onTestFailure(tr);
+        logTestResult(Status.FAILURE, tr, false);
+    }
+
+    @Override
+    public void onTestFailedButWithinSuccessPercentage(ITestResult tr) {
+        super.onTestFailedButWithinSuccessPercentage(tr);
+        logTestResult(Status.SUCCESS_PERCENTAGE_FAILURE, tr, false);
+    }
+
+    @Override
+    public void onTestSkipped(ITestResult tr) {
+        super.onTestSkipped(tr);
+        logTestResult(Status.SKIP, tr, false);
+    }
+
+    @Override
+    public void onTestSuccess(ITestResult tr) {
+        super.onTestSuccess(tr);
+        logTestResult(Status.SUCCESS, tr, false);
+    }
+
+    @Override
+    public void onStart(ITestContext ctx) {
+        suiteName = ctx.getName();//ctx.getSuite().getXmlSuite().getFileName();
+        log("RUNNING: Suite: \"" + suiteName + "\" containing \"" + ctx.getAllTestMethods().length + "\" Tests (config: " + ctx.getSuite().getXmlSuite().getFileName() + ")");
+    }
+
+    @Override
+    public void onFinish(ITestContext context) {
+        logResults();
+        suiteName = null;
+    }
+
+    private ITestNGMethod[] resultsToMethods(List<ITestResult> results) {
+        ITestNGMethod[] result = new ITestNGMethod[results.size()];
+        int i = 0;
+        for (ITestResult tr : results) {
+            result[i++] = tr.getMethod();
+        }
+        return result;
+    }
+
+    /**
+     * Print out test summary
+     */
+    private void logResults() {
+        //
+        // Log test summary
+        //
+        ITestNGMethod[] ft = resultsToMethods(getFailedTests());
+        StringBuilder sb = new StringBuilder("\n===============================================\n");
+        sb.append("    ").append(suiteName).append("\n");
+        sb.append("    Tests run: ").append(Utils.calculateInvokedMethodCount(getAllTestMethods()));
+        sb.append(", Failures: ").append(Utils.calculateInvokedMethodCount(ft));
+        sb.append(", Skips: ").append(Utils.calculateInvokedMethodCount(resultsToMethods(getSkippedTests())));
+        int confFailures = getConfigurationFailures().size();
+        int confSkips = getConfigurationSkips().size();
+        if (confFailures > 0 || confSkips > 0) {
+            sb.append("\n").append("    Configuration Failures: ").append(confFailures);
+            sb.append(", Skips: ").append(confSkips);
+        }
+        sb.append("\n===============================================");
+        log(sb.toString());
+    }
+
+    /**
+     * Log meaningful message for passed in arguments.
+     * Message itself is of form:
+     * $status: "$suiteName" - $methodDeclaration ($actualArguments) finished in $x ms ($run of $totalRuns)
+     *
+     * @param st status of passed in itr
+     * @param itr test result to be described
+     * @param isConfMethod is itr describing configuration method
+     */
+    private void logTestResult(Status st, ITestResult itr, boolean isConfMethod) {
+        StringBuilder sb = new StringBuilder();
+        String stackTrace = "";
+        switch (st) {
+            case STARTED:
+                sb.append("INVOKING");
+                break;
+            case SKIP:
+                sb.append("SKIPPED");
+                stackTrace = itr.getThrowable() != null
+                        ? Utils.stackTrace(itr.getThrowable(), false)[0] : "";
+                break;
+            case FAILURE:
+                sb.append("FAILED");
+                stackTrace = itr.getThrowable() != null
+                        ? Utils.stackTrace(itr.getThrowable(), false)[0] : "";
+                break;
+            case SUCCESS:
+                sb.append("PASSED");
+                break;
+            case SUCCESS_PERCENTAGE_FAILURE:
+                sb.append("PASSED with failures");
+                break;
+            default:
+                //not happen
+                throw new RuntimeException("Unsupported test status:" + itr.getStatus());
+        }
+        if (isConfMethod) {
+            sb.append(" CONFIGURATION: ");
+        } else {
+            sb.append(": ");
+        }
+        ITestNGMethod tm = itr.getMethod();
+        int identLevel = sb.length();
+        sb.append(getMethodDeclaration(tm));
+        Object[] params = itr.getParameters();
+        Class<?>[] paramTypes = tm.getConstructorOrMethod().getParameterTypes();
+        if (null != params && params.length > 0) {
+            // The error might be a data provider parameter mismatch, so make
+            // a special case here
+            if (params.length != paramTypes.length) {
+                sb.append("Wrong number of arguments were passed by the Data Provider: found ");
+                sb.append(params.length);
+                sb.append(" but expected ");
+                sb.append(paramTypes.length);
+            } else {
+                sb.append("(value(s): ");
+                for (int i = 0; i < params.length; i++) {
+                    if (i > 0) {
+                        sb.append(", ");
+                    }
+                    sb.append(Utils.toString(params[i], paramTypes[i]));
+                }
+                sb.append(")");
+
+            }
+        }
+        if (Status.STARTED != st) {
+            sb.append(" finished in ");
+            sb.append(itr.getEndMillis() - itr.getStartMillis());
+            sb.append(" ms");
+            if (!Utils.isStringEmpty(tm.getDescription())) {
+                sb.append("\n");
+                for (int i = 0; i < identLevel; i++) {
+                    sb.append(" ");
+                }
+                sb.append(tm.getDescription());
+            }
+            if (tm.getInvocationCount() > 1) {
+                sb.append(" (");
+                sb.append(tm.getCurrentInvocationCount());
+                sb.append(" of ");
+                sb.append(tm.getInvocationCount());
+                sb.append(")");
+            }
+            if (!Utils.isStringEmpty(stackTrace)) {
+                sb.append("\n").append(stackTrace.substring(0, stackTrace.lastIndexOf(System.getProperty("line.separator"))));
+            }
+        } else {
+            if (!isConfMethod && tm.getInvocationCount() > 1) {
+                sb.append(" success: ");
+                sb.append(tm.getSuccessPercentage());
+                sb.append("%");
+            }
+        }
+        log(sb.toString());
+    }
+
+    protected void log(String message) {
+        //prefix all output lines
+        System.out.println(message.replaceAll("(?m)^", prefix));
+    }
+
+    /**
+     *
+     * @param method method to be described
+     * @return FQN of a class + method declaration for a method passed in
+     *      ie. test.triangle.CheckCount.testCheckCount(java.lang.String)
+     */
+    private String getMethodDeclaration(ITestNGMethod method) {
+        //see Utils.detailedMethodName
+        //perhaps should rather adopt the original method instead
+        ConstructorOrMethod m = method.getConstructorOrMethod();
+        StringBuilder buf = new StringBuilder();
+        buf.append("\"");
+        if (suiteName != null) {
+            buf.append(suiteName);
+        } else {
+            buf.append("UNKNOWN");
+        }
+        buf.append("\"");
+        buf.append(" - ");
+        if (method.isBeforeSuiteConfiguration()) {
+            buf.append("@BeforeSuite ");
+        } else if (method.isBeforeTestConfiguration()) {
+            buf.append("@BeforeTest ");
+        } else if (method.isBeforeClassConfiguration()) {
+            buf.append("@BeforeClass ");
+        } else if (method.isBeforeGroupsConfiguration()) {
+            buf.append("@BeforeGroups ");
+        } else if (method.isBeforeMethodConfiguration()) {
+            buf.append("@BeforeMethod ");
+        } else if (method.isAfterMethodConfiguration()) {
+            buf.append("@AfterMethod ");
+        } else if (method.isAfterGroupsConfiguration()) {
+            buf.append("@AfterGroups ");
+        } else if (method.isAfterClassConfiguration()) {
+            buf.append("@AfterClass ");
+        } else if (method.isAfterTestConfiguration()) {
+            buf.append("@AfterTest ");
+        } else if (method.isAfterSuiteConfiguration()) {
+            buf.append("@AfterSuite ");
+        }
+        buf.append(m.getDeclaringClass().getName());
+        buf.append(".");
+        buf.append(m.getName());
+        buf.append("(");
+        int i = 0;
+        for (Class<?> p : m.getParameterTypes()) {
+            if (i++ > 0) {
+                buf.append(", ");
+            }
+            buf.append(p.getName());
+        }
+        buf.append(")");
+        return buf.toString();
+    }
+
+    @Override
+    public String toString() {
+        return "VerboseReporter{" + "suiteName=" + suiteName + '}';
+    }
+}