001/*
002 * (C) Copyright 2014-2015 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Julien Carsique
018 *
019 */
020
021package org.nuxeo.runtime.test;
022
023import java.util.List;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.junit.Assert;
028import org.junit.runner.Result;
029import org.junit.runner.notification.Failure;
030
031import junit.framework.AssertionFailedError;
032
033/**
034 * Utility class for working with {@link org.junit.runner.Result#getFailures()}
035 *
036 * @since 5.9.5
037 */
038public class Failures {
039    private static final Log log = LogFactory.getLog(Failures.class);
040
041    private List<Failure> failures;
042
043    public Failures(List<Failure> failures) {
044        this.failures = failures;
045    }
046
047    public Failures(Result result) {
048        failures = result.getFailures();
049    }
050
051    @Override
052    public String toString() {
053        StringBuilder sb = new StringBuilder();
054        int i = 1;
055        AssertionFailedError errors = new AssertionFailedError();
056        for (Failure failure : failures) {
057            sb.append("* Failure ")
058              .append(i)
059              .append(": ")
060              .append(failure.getTestHeader())
061              .append("\n")
062              .append(failure.getTrace())
063              .append("\n");
064            errors.addSuppressed(failure.getException());
065            i++;
066        }
067        if (errors.getSuppressed().length > 0) {
068            // Log because JUnit swallows some parts of the stack trace
069            log.debug(errors.getMessage(), errors);
070        }
071        return sb.toString();
072    }
073
074    /**
075     * Call {@link org.junit.Assert#fail(String)} with a nice expanded string if there are failures. It also replaces
076     * original failure messages with a custom one if originalMessage is not {@code null}.
077     *
078     * @param originalMessage Message to replace if found in a failure
079     * @param customMessage Custom message to use as replacement for originalMessage
080     */
081    public void fail(String originalMessage, String customMessage) {
082        if (failures.isEmpty()) {
083            Assert.fail(customMessage);
084        }
085        StringBuilder sb = new StringBuilder();
086        int i = 1;
087        AssertionFailedError errors = new AssertionFailedError(customMessage);
088        sb.append(customMessage);
089        for (Failure failure : failures) {
090            sb.append("\n* Failure ").append(i).append(": ");
091            String trace = failure.getTrace();
092            if (originalMessage != null && originalMessage.equals(failure.getMessage())) {
093                trace = trace.replaceAll(originalMessage, customMessage);
094            }
095            sb.append(failure.getTestHeader()).append("\n").append(trace);
096            errors.addSuppressed(failure.getException());
097            i++;
098        }
099        // Log because JUnit swallows some parts of the stack trace
100        log.debug(errors.getMessage(), errors);
101        Assert.fail(sb.toString());
102    }
103}