Skip to content

Instantly share code, notes, and snippets.

@alwarren
Last active May 1, 2019 15:11
Show Gist options
  • Save alwarren/163a488f120423f131326733b66d81db to your computer and use it in GitHub Desktop.
Save alwarren/163a488f120423f131326733b66d81db to your computer and use it in GitHub Desktop.
Using JUnit5 to unit test adherence to the API specification of an immutable data type Point.
import org.junit.jupiter.params.converter.*;
import java.lang.annotation.*;
/*******************************************************************************
* Name: Compare.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Parameter Annotation
******************************************************************************/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@ConvertWith(CompareConverter.class)
public @interface Compare {
}
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;
/*******************************************************************************
* Name: CompareConverter.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Argument Converter
******************************************************************************/
class CompareConverter implements ArgumentConverter {
@Override
public Integer convert(Object value, ParameterContext parameterContext) throws
ArgumentConversionException {
if (value instanceof String) {
String compare = ((String) value).toLowerCase();
switch (compare) {
case "equal":
return 0;
case "greater":
return 1;
case "less":
return -1;
}
}
throw new ArgumentConversionException("Illegal argument conversion");
}
}
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import static junit.framework.TestCase.assertEquals;
/**
* Date: 4/30/2019
* Description: Tests used to verify adherence to the API specification of an immutable data type Point.
*
* API Rspecification:
*
* public class Point implements Comparable<Point> {
* // provided not tested
* public Point(int x, int y) // constructs the point (x, y)
* public void draw() // draws this point
* public void drawTo(Point that) // draws the line segment from this point to that point
* public String toString() // string representation
*
* // assigned and tested
* public int compareTo(Point that) // compare two points by y-coordinates, breaking ties by x-coordinates
* public double slopeTo(Point that) // the slope between this point and that point
* public Comparator<Point> slopeOrder() // compare two points by slopes they make with this point
* }
*
* API Requirements:
*
* 1. The compareTo() method should compare points by their y-coordinates, breaking ties by their x-coordinates.
* Formally, the invoking point (x0, y0) is less than the argument point (x1, y1) if and only if
* either y0 < y1 or if y0 = y1 and x0 < x1.
*
* 2. The slopeTo() method should return the slope between the invoking point (x0, y0) and the argument
* point (x1, y1), which is given by the formula (y1 − y0) / (x1 − x0).
*
* Treat the slope of a horizontal line segment as positive zero;
* Treat the slope of a vertical line segment as positive infinity;
* Treat the slope of a degenerate line segment (between a point and itself) as negative infinity.
*
* 3. The slopeOrder() method should return a comparator that compares its two argument points by the slopes
* they make with the invoking point (x0, y0).
* Formally, the point (x1, y1) is less than the point (x2, y2) if and only if the
* slope (y1 − y0) / (x1 − x0) is less than the slope (y2 − y0) / (x2 − x0).
* Treat horizontal, vertical, and degenerate line segments as in the slopeTo() method.
*
* 4. Do not override the equals() or hashCode() methods.
*/
@DisplayName("Test Point Methods")
public class PointFunctionalTests {
private Point origin = new Point(0, 0);
@ParameterizedTest(name = "origin.compareTo({1}) = {0}")
@CsvFileSource(resources = "test_point_compare_to.txt")
@DisplayName("Verify Point.compareTo")
void should_verify_point_compare_to(@Compare int expected, @RadialPoint Point point) {
assertEquals(expected, origin.compareTo(point));
}
@ParameterizedTest(name = "origin.slopeTo({1}) = {0}")
@CsvFileSource(resources = "test_point_slope_to.txt")
@DisplayName("Verify Point.slopeTo")
void should_verify_point_slope_to(@Slope double expected, @RadialPoint Point point) {
assertEquals(expected, origin.slopeTo(point));
}
@ParameterizedTest(name = "origin.slopeOrder().compare({1}, {2}) = {0}")
@CsvFileSource(resources = "test_point_slope_order.txt")
@DisplayName("Verify Point.slopeOrder")
void should_verify_point_slope_order(@Compare int expected, @RadialPoint Point first, @RadialPoint Point second) {
assertEquals(expected, origin.slopeOrder().compare(first, second));
}
}
import org.junit.jupiter.params.converter.*;
import java.lang.annotation.*;
/*******************************************************************************
* Name: RadialPoint.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Parameter Annotation
******************************************************************************/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@ConvertWith(RadialPointConverter.class)
public @interface RadialPoint {
}
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;
/*******************************************************************************
* Name: RadialPointConverter.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Argument Converter
******************************************************************************/
class RadialPointConverter implements ArgumentConverter {
private Point origin = new Point(0, 0);
private Point p1 = new Point(0, 1);
private Point p2 = new Point(1, 1);
private Point p3 = new Point(1, 0);
private Point p4 = new Point(1, -1);
private Point p5 = new Point(0, -1);
private Point p6 = new Point(-1, -1);
private Point p7 = new Point(-1, 0);
private Point p8 = new Point(-1, 1);
@Override
public Point convert(Object value, ParameterContext parameterContext) throws
ArgumentConversionException {
if (value instanceof String) {
String point = ((String) value).toLowerCase();
switch (point) {
case "p0":
case "origin":
return origin;
case "p1":
return p1;
case "p2":
return p2;
case "p3":
return p3;
case "p4":
return p4;
case "p5":
return p5;
case "p6":
return p6;
case "p7":
return p7;
case "p8":
return p8;
}
}
throw new ArgumentConversionException("Illegal argument conversion");
}
}
import org.junit.jupiter.params.converter.*;
import java.lang.annotation.*;
/*******************************************************************************
* Name: Slope.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Parameter Annotation
******************************************************************************/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@ConvertWith(SlopeConverter.class)
public @interface Slope {
}
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.converter.ArgumentConversionException;
import org.junit.jupiter.params.converter.ArgumentConverter;
/*******************************************************************************
* Name: SlopeConverter.java
* Date: 4/30/2019
* Description: JUnit5 Parameterized Test Argument Converter
******************************************************************************/
class SlopeConverter implements ArgumentConverter {
@Override
public Double convert(Object value, ParameterContext parameterContext) throws
ArgumentConversionException {
if (value instanceof String) {
String slope = ((String) value).toLowerCase();
switch (slope) {
case "horizontal":
return +0.0;
case "degenerate":
return Double.NEGATIVE_INFINITY;
case "vertical":
return Double.POSITIVE_INFINITY;
case "45deg":
return 1.0;
case "135deg":
return -1.0;
case "225deg":
return 1.0;
case "315deg":
return -1.0;
}
}
throw new ArgumentConversionException("Illegal argument conversion");
}
}
equal,origin
less,p1
less,p2
less,p3
greater,p4
greater,p5
greater,p6
greater,p7
less,p8
equal, origin, origin
greater, p1, p7
greater, p2, p7
less, p3, p6
less, p4, p5
greater, p5, p4
greater, p6, p3
less, p7, p2
less, p8, p1
degenerate, origin
vertical, p1
45deg, p2
horizontal, p3
135deg, p4
vertical, p5
225deg, p6
horizontal, p7
315deg, p8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment