aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/junit/runner/Result.java
blob: ff53b084375fcabd1f6b7eeb22f06cd9780fab79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package org.junit.runner;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

/**
 * A <code>Result</code> collects and summarizes information from running multiple tests.
 * All tests are counted -- additional information is collected from tests that fail.
 *
 * @since 4.0
 */
public class Result implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final ObjectStreamField[] serialPersistentFields =
            ObjectStreamClass.lookup(SerializedForm.class).getFields();
    private final AtomicInteger count;
    private final AtomicInteger ignoreCount;
    private final AtomicInteger assumptionFailureCount;
    private final CopyOnWriteArrayList<Failure> failures;
    private final AtomicLong runTime;
    private final AtomicLong startTime;

    /** Only set during deserialization process. */
    private SerializedForm serializedForm;

    public Result() {
        count = new AtomicInteger();
        ignoreCount = new AtomicInteger();
        assumptionFailureCount = new AtomicInteger();
        failures = new CopyOnWriteArrayList<Failure>();
        runTime = new AtomicLong();
        startTime = new AtomicLong();
    }

    private Result(SerializedForm serializedForm) {
        count = serializedForm.fCount;
        ignoreCount = serializedForm.fIgnoreCount;
        assumptionFailureCount = serializedForm.assumptionFailureCount;
        failures = new CopyOnWriteArrayList<Failure>(serializedForm.fFailures);
        runTime = new AtomicLong(serializedForm.fRunTime);
        startTime = new AtomicLong(serializedForm.fStartTime);
    }

    /**
     * Returns the number of tests run
     */
    public int getRunCount() {
        return count.get();
    }

    /**
     * Returns the number of tests that failed during the run
     */
    public int getFailureCount() {
        return failures.size();
    }

    /**
     * Returns the number of milliseconds it took to run the entire suite to run
     */
    public long getRunTime() {
        return runTime.get();
    }

    /**
     * Returns the {@link Failure}s describing tests that failed and the problems they encountered
     */
    public List<Failure> getFailures() {
        return failures;
    }

    /**
     * @return the number of tests ignored during the run
     */
    public int getIgnoreCount() {
        return ignoreCount.get();
    }

    /**
     * Returns the number of tests skipped because of an assumption failure
     *
     * @throws UnsupportedOperationException if the result was serialized in a version before JUnit 4.13
     * @since 4.13
     */
    public int getAssumptionFailureCount() {
        if (assumptionFailureCount == null) {
            throw new UnsupportedOperationException(
                    "Result was serialized from a version of JUnit that doesn't support this method");
        }
        return assumptionFailureCount.get();
    }

    /**
     * @return <code>true</code> if all tests succeeded
     */
    public boolean wasSuccessful() {
        return getFailureCount() == 0;
    }

    private void writeObject(ObjectOutputStream s) throws IOException {
        SerializedForm serializedForm = new SerializedForm(this);
        serializedForm.serialize(s);
    }

    private void readObject(ObjectInputStream s)
            throws ClassNotFoundException, IOException {
        serializedForm = SerializedForm.deserialize(s);
    }

    private Object readResolve()  {
        return new Result(serializedForm);
    }

    @RunListener.ThreadSafe
    private class Listener extends RunListener {
        @Override
        public void testRunStarted(Description description) throws Exception {
            startTime.set(System.currentTimeMillis());
        }

        @Override
        public void testRunFinished(Result result) throws Exception {
            long endTime = System.currentTimeMillis();
            runTime.addAndGet(endTime - startTime.get());
        }

        @Override
        public void testFinished(Description description) throws Exception {
            count.getAndIncrement();
        }

        @Override
        public void testFailure(Failure failure) throws Exception {
            failures.add(failure);
        }

        @Override
        public void testIgnored(Description description) throws Exception {
            ignoreCount.getAndIncrement();
        }

        @Override
        public void testAssumptionFailure(Failure failure) {
            assumptionFailureCount.getAndIncrement();
        }
    }

    /**
     * Internal use only.
     */
    public RunListener createListener() {
        return new Listener();
    }

    /**
     * Represents the serialized output of {@code Result}. The fields on this
     * class match the files that {@code Result} had in JUnit 4.11.
     */
    private static class SerializedForm implements Serializable {
        private static final long serialVersionUID = 1L;
        private final AtomicInteger fCount;
        private final AtomicInteger fIgnoreCount;
        private final AtomicInteger assumptionFailureCount;
        private final List<Failure> fFailures;
        private final long fRunTime;
        private final long fStartTime;

        public SerializedForm(Result result) {
            fCount = result.count;
            fIgnoreCount = result.ignoreCount;
            assumptionFailureCount = result.assumptionFailureCount;
            fFailures = Collections.synchronizedList(new ArrayList<Failure>(result.failures));
            fRunTime = result.runTime.longValue();
            fStartTime = result.startTime.longValue();
        }

        @SuppressWarnings("unchecked")
        private SerializedForm(ObjectInputStream.GetField fields) throws IOException, ClassNotFoundException {
            fCount = (AtomicInteger) fields.get("fCount", null);
            fIgnoreCount = (AtomicInteger) fields.get("fIgnoreCount", null);
            assumptionFailureCount = (AtomicInteger) fields.get("assumptionFailureCount", null);
            fFailures = (List<Failure>) fields.get("fFailures", null);
            fRunTime = fields.get("fRunTime", 0L);
            fStartTime = fields.get("fStartTime", 0L);
        }

        public void serialize(ObjectOutputStream s) throws IOException {
            ObjectOutputStream.PutField fields = s.putFields();
            fields.put("fCount", fCount);
            fields.put("fIgnoreCount", fIgnoreCount);
            fields.put("fFailures", fFailures);
            fields.put("fRunTime", fRunTime);
            fields.put("fStartTime", fStartTime);
            fields.put("assumptionFailureCount", assumptionFailureCount);
            s.writeFields();
        }

        public static SerializedForm deserialize(ObjectInputStream s)
                throws ClassNotFoundException, IOException {
            ObjectInputStream.GetField fields = s.readFields();
            return new SerializedForm(fields);
        }
    }
}