Skip to content

Commit d7f47e9

Browse files
Merge pull request #63 from JoyOfCodingPDX/issue-59/fail-koan-if-no-assert-call
Address #59 so that a Koan fails if it has no assertion statement.
2 parents 7201365 + 163b38e commit d7f47e9

18 files changed

Lines changed: 180 additions & 22 deletions

File tree

koans/app/config/PathToEnlightenment.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
<packages>
33
<package pkg="beginner" name="Novice">
44
<suite class="AboutKoans">
5-
<koan name="findAboutKoansFile" displayIncompleteKoanException="false" />
6-
<koan name="definitionOfKoanCompletion" displayIncompleteKoanException="false" />
5+
<koan name="findAboutKoansFile" displayIncompleteKoanException="false" requireAssertion="false" />
6+
<koan name="definitionOfKoanCompletion" displayIncompleteKoanException="false" requireAssertion="false" />
77
</suite>
88
<suite class="AboutAssertions"/>
99
<suite class="AboutEquality"/>

koans/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
<parent>
55
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
66
<artifactId>koans-parent</artifactId>
7-
<version>1.2.4-SNAPSHOT</version>
7+
<version>1.3.0-SNAPSHOT</version>
88
</parent>
99
<artifactId>java-koans</artifactId>
1010
<packaging>jar</packaging>
11-
<version>1.2.4-SNAPSHOT</version>
11+
<version>1.3.0-SNAPSHOT</version>
1212
<name>Java Koans</name>
1313
<inceptionYear>2012</inceptionYear>
1414
<description>Java Koans to learn the Java language and APIs</description>
@@ -64,7 +64,7 @@
6464
<dependency>
6565
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
6666
<artifactId>koans-lib</artifactId>
67-
<version>1.2.3</version>
67+
<version>1.3.0-SNAPSHOT</version>
6868
</dependency>
6969
</dependencies>
7070
<properties>

koans/src/advanced/AboutMocks.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.sandwich.koan.Koan;
44

5+
import static com.sandwich.util.Assert.assertTrue;
56
import static com.sandwich.util.Assert.fail;
67

78
public class AboutMocks {
@@ -40,7 +41,7 @@ public void simpleAnonymousMock() {
4041
// HINT: pass a safe Collaborator implementation to constructor
4142
// new ClassUnderTest(new Collaborator(){... it should not be the
4243
// objective of this test to test that collaborator, so replace it
43-
new ClassUnderTest().doSomething();
44+
assertTrue(new ClassUnderTest().doSomething());
4445
}
4546

4647
}

koans/src/beginner/AboutArrays.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public void arrayIndexOutOfBounds() {
6666
int[] array = new int[]{1};
6767
@SuppressWarnings("unused")
6868
int meh = array[1]; // remember 0 based indexes, 1 is the 2nd element (which doesn't exist)
69+
assertEquals(meh, __);
6970
}
7071

7172
@Koan

koans/src/beginner/AboutExceptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import static com.sandwich.koan.constant.KoanConstants.__;
88
import static com.sandwich.util.Assert.assertEquals;
9+
import static com.sandwich.util.Assert.assertTrue;
910

1011
public class AboutExceptions {
1112

@@ -103,6 +104,7 @@ private void doUncheckedStuff() {
103104
public void catchUncheckedExceptions() {
104105
// What do you need to do to catch the unchecked exception?
105106
doUncheckedStuff();
107+
assertTrue(true);
106108
}
107109

108110
@SuppressWarnings("serial")

lib/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
<parent>
55
<groupId>io.github.davidwhitlock.joy.com.sandwich</groupId>
66
<artifactId>koans-parent</artifactId>
7-
<version>1.2.4-SNAPSHOT</version>
7+
<version>1.3.0-SNAPSHOT</version>
88
</parent>
99
<artifactId>koans-lib</artifactId>
1010
<packaging>jar</packaging>
11-
<version>1.2.4-SNAPSHOT</version>
11+
<version>1.3.0-SNAPSHOT</version>
1212
<name>Java Koans Framework</name>
1313
<description>Supporting library code for running Java Koans</description>
1414
<url>https://github.com/DavidWhitlock/java-koans</url>

lib/src/main/java/com/sandwich/koan/KoanMethod.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class KoanMethod {
1111
private final transient Method method;
1212
private final String lesson;
1313
private final boolean displayIncompleteException;
14+
private final boolean requiresAssertion;
1415
private static final KoanSuiteCompilationListener listener = new KoanSuiteCompilationListener();
1516

1617
private KoanMethod(KoanElementAttributes koanAttributes) throws SecurityException, NoSuchMethodException{
@@ -26,27 +27,33 @@ public static KoanMethod getInstance(KoanElementAttributes koanAttributes){
2627
}
2728

2829
public static KoanMethod getInstance(Method method){
29-
return new KoanMethod(null, method, true);
30+
return new KoanMethod(null, method, true, true);
31+
}
32+
33+
public static KoanMethod getInstance(Method method, boolean requiresAssertion){
34+
return new KoanMethod(null, method, true, requiresAssertion);
3035
}
3136

3237
public static KoanMethod getInstance(String lesson, Method method){
33-
return new KoanMethod(lesson, method, true);
38+
return new KoanMethod(lesson, method, true, true);
3439
}
3540

36-
private KoanMethod(String lesson, Method method, boolean displayIncompleteException){
41+
private KoanMethod(String lesson, Method method, boolean displayIncompleteException, boolean requiresAssertion){
3742
if(method == null){
3843
throw new IllegalArgumentException("method may not be null");
3944
}
4045
this.method = method;
4146
this.lesson = new RbVariableInjector(lesson, method).injectLessonVariables();
4247
this.displayIncompleteException = displayIncompleteException;
48+
this.requiresAssertion = requiresAssertion;
4349
}
4450

4551
public KoanMethod(String lesson, KoanElementAttributes koanAttributes) throws SecurityException, NoSuchMethodException {
4652
this( lesson,
4753
KoanClassLoader.getInstance().loadClass(koanAttributes.className, listener)
4854
.getMethod(koanAttributes.name),
49-
!"false".equalsIgnoreCase(koanAttributes.displayIncompleteKoanException));
55+
!"false".equalsIgnoreCase(koanAttributes.displayIncompleteKoanException),
56+
!"false".equalsIgnoreCase(koanAttributes.requireAssertion));
5057
}
5158

5259
public String getLesson() {
@@ -60,9 +67,13 @@ public Method getMethod() {
6067
public boolean displayIncompleteException() {
6168
return displayIncompleteException;
6269
}
70+
71+
public boolean requiresAssertion() {
72+
return requiresAssertion;
73+
}
6374

6475
public KoanMethod clone(Method method){
65-
return new KoanMethod(lesson, method, displayIncompleteException);
76+
return new KoanMethod(lesson, method, displayIncompleteException, requiresAssertion);
6677
}
6778

6879
@Override public String toString(){
@@ -75,6 +86,7 @@ public int hashCode() {
7586
final int prime = 31;
7687
int result = 1;
7788
result = prime * result + (displayIncompleteException ? 1231 : 1237);
89+
result = prime * result + (requiresAssertion ? 1231 : 1237);
7890
result = prime * result + ((lesson == null) ? 0 : lesson.hashCode());
7991
return result;
8092
}
@@ -90,6 +102,8 @@ public boolean equals(Object obj) {
90102
KoanMethod other = (KoanMethod) obj;
91103
if (displayIncompleteException != other.displayIncompleteException)
92104
return false;
105+
if (requiresAssertion != other.requiresAssertion)
106+
return false;
93107
if (lesson == null) {
94108
if (other.lesson != null)
95109
return false;

lib/src/main/java/com/sandwich/koan/path/xmltransformation/KoanElementAttributes.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
public class KoanElementAttributes{
55

6-
public String name, displayIncompleteKoanException, className;
6+
public String name, displayIncompleteKoanException, requireAssertion, className;
77

8-
public KoanElementAttributes(String name, String displayIncompleteKoanException, String className){
8+
public KoanElementAttributes(String name, String displayIncompleteKoanException, String requireAssertion, String className){
99
this.name = name;
1010
this.displayIncompleteKoanException = displayIncompleteKoanException;
11+
this.requireAssertion = requireAssertion;
1112
this.className = className;
1213
}
1314

@@ -21,6 +22,8 @@ public int hashCode() {
2122
* result
2223
+ ((displayIncompleteKoanException == null) ? 0
2324
: displayIncompleteKoanException.hashCode());
25+
result = prime * result
26+
+ ((requireAssertion == null) ? 0 : requireAssertion.hashCode());
2427
result = prime * result + ((name == null) ? 0 : name.hashCode());
2528
return result;
2629
}
@@ -45,6 +48,11 @@ public boolean equals(Object obj) {
4548
} else if (!displayIncompleteKoanException
4649
.equals(other.displayIncompleteKoanException))
4750
return false;
51+
if (requireAssertion == null) {
52+
if (other.requireAssertion != null)
53+
return false;
54+
} else if (!requireAssertion.equals(other.requireAssertion))
55+
return false;
4856
if (name == null) {
4957
if (other.name != null)
5058
return false;
@@ -57,7 +65,8 @@ public boolean equals(Object obj) {
5765
public String toString() {
5866
return "KoanElementAttributes [name=" + name
5967
+ ", displayIncompleteKoanException="
60-
+ displayIncompleteKoanException + ", className=" + className
68+
+ displayIncompleteKoanException + ", requireAssertion="
69+
+ requireAssertion + ", className=" + className
6170
+ "]";
6271
}
6372

lib/src/main/java/com/sandwich/koan/path/xmltransformation/XmlToPathTransformerImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,14 @@ Map<String, KoanElementAttributes> extractKoansAndRawLessons(
9595
.getNamedItem("displayIncompleteKoanException");
9696
String displayIncompleteKoanException = displayKoanIncompleteExceptionNode == null ? null
9797
: displayKoanIncompleteExceptionNode.getNodeValue();
98+
Node requireAssertionNode = attributes.getNamedItem("requireAssertion");
99+
String requireAssertion = requireAssertionNode == null ? null
100+
: requireAssertionNode.getNodeValue();
98101
if (rawKoanAttributesByMethodName.containsKey(name)) {
99102
throw new DuplicateKoanException(className, name);
100103
}
101104
rawKoanAttributesByMethodName.put(name, new KoanElementAttributes(
102-
name, displayIncompleteKoanException, className));
105+
name, displayIncompleteKoanException, requireAssertion, className));
103106
}
104107
}
105108
return rawKoanAttributesByMethodName;
@@ -113,4 +116,3 @@ public DuplicateKoanException(String className, String name){
113116
}
114117

115118
}
116-

lib/src/main/java/com/sandwich/koan/runner/KoanMethodRunner.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.sandwich.koan.constant.KoanConstants;
1616
import com.sandwich.koan.result.KoanMethodResult;
1717
import com.sandwich.util.ExceptionUtils;
18+
import com.sandwich.util.Assert;
1819
import com.sandwich.util.Strings;
1920
import com.sandwich.util.io.directories.DirectoryManager;
2021
import com.sandwich.util.io.filecompiler.CompilerConfig;
@@ -23,12 +24,17 @@
2324
public class KoanMethodRunner {
2425

2526
private static final String EXPECTED_PROPERTY_KEY = "expected";
27+
private static final String NO_ASSERTION_MESSAGE = "No assertion was invoked in this koan.";
2628

2729
public static KoanMethodResult run(Object suite, KoanMethod koan){
30+
Assert.resetAssertionTracking();
2831
try {
2932
Method method = koan.getMethod();
3033
method.setAccessible(true);
3134
method.invoke(suite);
35+
if(koan.requiresAssertion() && !Assert.wasAssertionInvoked()){
36+
return new KoanMethodResult(koan, NO_ASSERTION_MESSAGE, null);
37+
}
3238
} catch (Throwable t) {
3339
Throwable tempException = t;
3440
String message = ExceptionUtils.convertToPopulatedStackTraceString(t);
@@ -44,6 +50,8 @@ public static KoanMethodResult run(Object suite, KoanMethod koan){
4450
tempException = tempException.getCause();
4551
}
4652
return new KoanMethodResult(koan, message, getOriginalLineNumber(t, suite.getClass()));
53+
} finally {
54+
Assert.resetAssertionTracking();
4755
}
4856
return KoanMethodResult.PASSED;
4957
}
@@ -84,4 +92,4 @@ static String getOriginalLineNumber(Throwable t, Class<?> failingSuite){
8492
return null;
8593
}
8694

87-
}
95+
}

0 commit comments

Comments
 (0)