Skip to content

Instantly share code, notes, and snippets.

@jexp
Last active August 29, 2015 14:07
Show Gist options
  • Save jexp/949af62487473bfac2d4 to your computer and use it in GitHub Desktop.
Save jexp/949af62487473bfac2d4 to your computer and use it in GitHub Desktop.
jQAssistant concept and constraint definitions as AsciiDoc (http://jqassistant.org | http://github.com/buschmais/jqassistant)
package jexp.adoc;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.ast.ContentPart;
import org.asciidoctor.ast.DocumentHeader;
import org.asciidoctor.ast.StructuredDocument;
import java.io.File;
import java.util.*;
/**
* @author mh
* @since 11.10.14
*/
public class JQAssistantReader {
public static void main(String[] args) {
Asciidoctor asciidoctor = Asciidoctor.Factory.create();
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(Asciidoctor.STRUCTURE_MAX_LEVEL, 10);
StructuredDocument doc = asciidoctor.readDocumentStructure(new File(args[0]), parameters);
DocumentHeader header = doc.getHeader();
System.out.println("Title: " + header.getDocumentTitle().getMain());
System.out.println("Author: " + header.getAuthor());
System.out.println("Version: " + header.getAttributes().get("version"));
System.out.println("\nSections: \n");
List<ContentPart> partsByContext = doc.getPartsByContext("section");
for (ContentPart section : partsByContext) {
System.out.println("title: " + section.getTitle().getMain());
}
System.out.println("\nConcepts: \n");
for (ContentPart concept : findListings(doc, "concept")) {
dump(concept);
}
System.out.println("\nConstraints: \n");
for (ContentPart constraint : findListings(doc, "constraint")) {
dump(constraint);
}
}
private static Collection<ContentPart> findListings(StructuredDocument doc, String role) {
Set<ContentPart> result = new LinkedHashSet<ContentPart>();
result.addAll(findListings(doc.getParts(), role));
return result;
}
private static Collection<ContentPart> findListings(Collection<ContentPart> parts, String role) {
Set<ContentPart> result = new LinkedHashSet<ContentPart>();
if (parts != null) {
for (ContentPart part : parts) {
if (role.equals(part.getRole()) &&
"listing".equals(part.getContext()) && "source".equals(part.getStyle()) && "cypher".equals(part.getAttributes().get("language"))) {
result.add(part);
}
result.addAll(findListings(part.getParts(), role));
}
}
return result;
}
private static void dump(ContentPart contentPart) {
Map<String, Object> attributes = contentPart.getAttributes();
System.out.printf("Title: %s %n%nid '%s' context '%s' role '%s' style '%s' lang '%s' depends '%s'%n---%n%s%n",
attributes.get("title"),
contentPart.getId(),
contentPart.getContext(),
contentPart.getRole(),
contentPart.getStyle(),
attributes.get("language"),
attributes.get("depends"),
contentPart.getContent()
);
}
}

Find JUnit tests without assertions

As a follow up of the last post Find JUnit assertions without a message another useful constraint can be created using a set of cypher queries.

How can we find all test implementations which do not perform any assertion?

Java Test Example

Here’s an example Java class:

@Test
public void test() {
  // prepare data
  int a = 1;
  int b = 2;
  // call the method which shall be tested
  int result = myService.add(a, b);
  // no verification if the result is correct
}

The following set of jQAssistant rules report such kind of test implementations, they consist of two concepts:

Concepts

Finds test methods (i.e. annotated with @org.junit.Test) and labels them and their containing classes with :Test and :Junit4.
match
  (c:Type:Class)-[:DECLARES]->(m:Method),
  (m)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
where
  a.fqn="org.junit.Test"
set
  c:Test:Junit4, m:Test:Junit4
return
  c as TestClass, collect(m) as TestMethods
Labels all assertion methods declared by org.junit.Assert with :Assert.
match
    (assertType:Type)-[:DECLARES]->(assertMethod)
where
    assertType.fqn = 'org.junit.Assert'
    and assertMethod.signature =~ 'void assert.*'
set
    assertMethod:Assert
return
    assertMethod

Constraints

and the constraint:

All test methods must perform assertions.
match
  (testType:Type)-[:DECLARES]->(testMethod:Test:Method)
where
  not (testMethod)-[:INVOKES*]->(:Method:Assert)
return
  testType as DeclaringType,
  testMethod as Method

Conclusion

The concept junit4:TestClassOrMethod adds a label :Test to all test methods annotated with @org.junit.Test, the concept junit4:AssertMethod adds a label : Assert to all assert methods provided by org.junit.Assert.

Both are required by the constraint junit4:TestMethodWithoutAssertion which does nothing more than checking if within the call graph starting at a test method (i.e. traversal over all outgoing :INVOKE relationships), at least one :Assert labeled method can be found.

[[junit-without-assertions]]
= Find JUnit tests without assertions
:author: Dirk Mahler
:version: 1.0.0-M03+
As a follow up of the last post http://jqassistant.org/junit-assertions-without-message/[Find JUnit assertions without a message] another useful constraint can be created using a set of cypher queries.
How can we find all test implementations which do not perform any assertion?
== Java Test Example
Here’s an example Java class:
[source,java]
----
@Test
public void test() {
// prepare data
int a = 1;
int b = 2;
// call the method which shall be tested
int result = myService.add(a, b);
// no verification if the result is correct
}
----
The following set of jQAssistant rules report such kind of test implementations, they consist of two concepts:
== Concepts
[[junit4:TestClassOrMethod]]
.Finds test methods (i.e. annotated with `@org.junit.Test`) and labels them and their containing classes with `:Test` and `:Junit4`.
[source,cypher,role=concept]
----
match
(c:Type:Class)-[:DECLARES]->(m:Method),
(m)-[:ANNOTATED_BY]-()-[:OF_TYPE]->(a:Type)
where
a.fqn="org.junit.Test"
set
c:Test:Junit4, m:Test:Junit4
return
c as TestClass, collect(m) as TestMethods
----
.Labels all assertion methods declared by `org.junit.Assert` with `:Assert`.
[source.concept#junit4:AssertMethod,cypher]
----
match
(assertType:Type)-[:DECLARES]->(assertMethod)
where
assertType.fqn = 'org.junit.Assert'
and assertMethod.signature =~ 'void assert.*'
set
assertMethod:Assert
return
assertMethod
----
== Constraints
and the constraint:
[[junit4:TestMethodWithoutAssertion]]
.All test methods must perform assertions.
[source,cypher,role=constraint,depends="junit4:TestClassOrMethod,junit4:AssertMethod"]]
----
match
(testType:Type)-[:DECLARES]->(testMethod:Test:Method)
where
not (testMethod)-[:INVOKES*]->(:Method:Assert)
return
testType as DeclaringType,
testMethod as Method
----
== Conclusion
The concept `junit4:TestClassOrMethod` adds a label `:Test` to all test methods annotated with `@org.junit.Test`,
the concept `junit4:AssertMethod` adds a label `: Assert` to all assert methods provided by `org.junit.Assert`.
Both are required by the constraint `junit4:TestMethodWithoutAssertion` which does nothing more than checking
if within the call graph starting at a test method (i.e. traversal over all outgoing `:INVOKE` relationships),
at least one `:Assert` labeled method can be found.
Title: Find JUnit tests without assertions
Author: Dirk Mahler
Version: 1.0.0-M03+
Sections:
title: Java Test Example
title: Concepts
title: Constraints
title: Conclusion
Concepts:
Title: Finds test methods (i.e. annotated with `@org.junit.Test`) and labels them and their containing classes with `:Test` and `:Junit4`.
id 'junit4:TestClassOrMethod' context 'listing' role 'concept' style 'source' lang 'cypher' depends 'null'
---
match
(c:Type:Class)-[:DECLARES]-&gt;(m:Method),
(m)-[:ANNOTATED_BY]-()-[:OF_TYPE]-&gt;(a:Type)
where
a.fqn="org.junit.Test"
set
c:Test:Junit4, m:Test:Junit4
return
c as TestClass, collect(m) as TestMethods
Title: Labels all assertion methods declared by `org.junit.Assert` with `:Assert`.
id 'junit4:AssertMethod' context 'listing' role 'concept' style 'source' lang 'cypher' depends 'null'
---
match
(assertType:Type)-[:DECLARES]-&gt;(assertMethod)
where
assertType.fqn = 'org.junit.Assert'
and assertMethod.signature =~ 'void assert.*'
set
assertMethod:Assert
return
assertMethod
Constraints:
Title: All test methods must perform assertions.
id 'junit4:TestMethodWithoutAssertion' context 'listing' role 'constraint' style 'source' lang 'cypher' depends 'junit4:TestClassOrMethod,junit4:AssertMethod'
---
match
(testType:Type)-[:DECLARES]-&gt;(testMethod:Test:Method)
where
not (testMethod)-[:INVOKES*]-&gt;(:Method:Assert)
return
testType as DeclaringType,
testMethod as Method
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jexp</groupId>
<artifactId>asciidoctor-test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment