001/** 002 * Powerunit - A JDK1.8 test framework 003 * Copyright (C) 2014 Mathieu Boretti. 004 * 005 * This file is part of Powerunit 006 * 007 * Powerunit is free software: you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Powerunit is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Powerunit. If not, see <http://www.gnu.org/licenses/>. 019 */ 020package ch.powerunit; 021 022import java.lang.annotation.Documented; 023import java.lang.annotation.ElementType; 024import java.lang.annotation.Retention; 025import java.lang.annotation.RetentionPolicy; 026import java.lang.annotation.Target; 027 028/** 029 * Mark a method as being a test method. 030 * <p> 031 * This method must be public, non static, 0-arg, void return. 032 * 033 * @author borettim 034 * 035 */ 036@Documented 037@Retention(RetentionPolicy.RUNTIME) 038@Target(ElementType.METHOD) 039public @interface Test { 040 /** 041 * Define an alternative name for the test. 042 * <p> 043 * If not used, the test name will be based on the method name. In case of 044 * parameterized test, the name will be formatted in the same way that the 045 * {@link Parameters @Parameters} annotation will be. 046 * 047 * @return the name 048 * @see Parameters#value() For the exact syntax of the name model. 049 * @see java.text.MessageFormat#format(String, Object...) The formatter used 050 * for parameterized test. For version before 0.4.0. 051 * @see java.lang.String#format(String, Object...) The formatter used for 052 * parameterized test, since version 0.4.0. 053 */ 054 String name() default ""; 055 056 /** 057 * Define if the test must fail at the first assertion/failure in error 058 * (default) or only at the end (and accumulate all expected error). 059 * <p> 060 * The goal is here to change the fail assertion and failure work ; When set 061 * to <code>false</code>. Assertion/failure will not stop the test, but 062 * return false. It is up to the test itself to define what to be done based 063 * on this return value (continue, return, etc). At the end of the test, if 064 * any failure happened, a general failure will be produced, with detail 065 * regarding all failures. <br> 066 * For example, a test may look like : 067 * 068 * <pre> 069 * public class LaterFailureTest implements TestSuite { 070 * @Test(fastFail = false) 071 * public void test() { 072 * assertThat(true).is(false); 073 * assertWhen((p) -> { 074 * }).throwException(any(Throwable.class)); 075 * fail("demo"); 076 * } 077 * } 078 * </pre> 079 * 080 * And the result like: 081 * 082 * <pre> 083 * Multiple failures : 084 * Error : expecting <false> but was <true> 085 * Error : An exception was expected, but none was thrown 086 * Error : demo 087 * 088 * Original Stack Traces 089 * expecting <false> but was <true> 090 * ch.powerunit.impl.AssertThatObjectImpl.is(AssertThatObjectImpl.java:63) 091 * ... 092 * An exception was expected, but none was thrown 093 * ch.powerunit.impl.AssertThatExceptionImpl.throwException(AssertThatExceptionImpl.java:64) 094 * ... 095 * demo 096 * ch.powerunit.Assert.fail(Assert.java:578) 097 * ... 098 * 099 * ch.powerunit.impl.TestContextImpl.fail(TestContextImpl.java:115) 100 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl.lambda$null$104(DefaultPowerUnitRunnerImpl.java:505) 101 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl$$Lambda$38/665188480.run(Unknown Source) 102 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl.lambda$runOne$73(DefaultPowerUnitRunnerImpl.java:226) 103 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl$$Lambda$42/520022247.accept(Unknown Source) 104 * java.util.HashMap$EntrySet.forEach(HashMap.java:1035) 105 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl.runOne(DefaultPowerUnitRunnerImpl.java:210) 106 * ch.powerunit.impl.DefaultPowerUnitRunnerImpl.run(DefaultPowerUnitRunnerImpl.java:144) 107 * ch.powerunit.PowerUnitMainRunner.main(PowerUnitMainRunner.java:82) 108 * ch.powerunit.suite.Suites.main(Suites.java:73) 109 * </pre> 110 * 111 * <br> 112 * This function will only function in the following case : 113 * <ul> 114 * <li>The assertion method is used from the same thread that the test 115 * itself (it is the standard case).</li> 116 * <li>The assertion method is used directement from the object test, and 117 * this class implements {@link TestSuite}.</li> 118 * </ul> 119 * 120 * <h3>Examples</h3> 121 * <h4>Using two threads without fastFail</h4> 122 * Let's assume the following test class : 123 * 124 * <pre> 125 * import ch.powerunit.Rule; 126 * import ch.powerunit.Test; 127 * import ch.powerunit.TestRule; 128 * import ch.powerunit.TestSuite; 129 * 130 * public class MyBean4Test implements TestSuite { 131 * @Rule 132 * public final TestRule rule = before(this::prepare); 133 * 134 * private MyBean bean; 135 * 136 * private void prepare() { 137 * bean = new MyBean(); 138 * } 139 * 140 * @Test() 141 * public void testSimple() throws Exception { 142 * Thread t = new Thread(() -> { 143 * bean.setField1("y"); 144 * assertThat(bean.getField1()).is("x"); 145 * }); 146 * t.start(); 147 * t.join(); 148 * } 149 * } 150 * </pre> 151 * 152 * <b>This test will not fail!</b>. Why ? because simply the assertion 153 * failure happend in another thread, so this thread receive an assertion 154 * failure, not the once supporting the test. 155 * 156 * <h4>Using two threads inside the same class, with fastFail</h4> 157 * Let's assume the following test class 158 * 159 * <pre> 160 * import ch.powerunit.Rule; 161 * import ch.powerunit.Test; 162 * import ch.powerunit.TestRule; 163 * import ch.powerunit.TestSuite; 164 * 165 * public class MyBean3Test implements TestSuite { 166 * @Rule 167 * public final TestRule rule = before(this::prepare); 168 * 169 * private MyBean bean; 170 * 171 * private void prepare() { 172 * bean = new MyBean(); 173 * } 174 * 175 * @Test(fastFail = false) 176 * public void testSimple() throws Exception { 177 * Thread t = new Thread(() -> { 178 * bean.setField1("y"); 179 * assertThat(bean.getField1()).is("x"); 180 * }); 181 * t.start(); 182 * t.join(); 183 * } 184 * } 185 * </pre> 186 * 187 * <b>This test will fail!</b>. Why ? because the fastFail mode will make 188 * the <code>assertThat</code> method only register the failure, and produce 189 * an error in the test thread. the link between the two threads is found 190 * because the <code>assertThat</code> method used is the one from the test 191 * class itself. 192 * 193 * @return true by default. 194 * @since 0.4.0 195 */ 196 boolean fastFail() default true; 197}