Skip to content

Commit 4710144

Browse files
authored
#major: 4.0.0
Breaking changes for Serializers, Comparators & Reporters - Now accept a Snapshot class as the argument - Still have access to everything they had before via the getters - Exposed lots more information for the serializer to customise the snapshot as desired Snapshot Headers - Users can now use custom headers via expect.header("A", "B").toMatchSnapshot(obj) - These headers are serialized into the snapshot as a JSON Object - Certain headers may be added as default in future versions REGEX matching - The Snapshot object is now parsed as a regular expression and key pieces of information are extracted No more varargs - Removed varargs param for `.toMatchSnapshot`. It now only supports a single argument. Remove onSaveSnapshotFile() hook - This made the file difficult to parse via a REGEX
1 parent 890c406 commit 4710144

File tree

71 files changed

+1000
-653
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1000
-653
lines changed

.github/workflows/build.yml

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ name: build
55

66
on:
77
push:
8-
branches: [ master ]
8+
branches:
9+
- master
10+
- 'release/**'
911
pull_request:
10-
branches: [ master ]
12+
branches:
13+
- master
14+
- 'release/**'
1115
workflow_dispatch:
1216

1317
jobs:

README.md

+131-104
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
[![Build Status](https://github.com/origin-energy/java-snapshot-testing/workflows/build/badge.svg)](https://github.com/origin-energy/java-snapshot-testing/actions)
2-
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.origin-energy/java-snapshot-testing-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.origin-energy/java-snapshot-testing-core)
2+
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.origin-energy/java-snapshot-testing-core/badge.svg?version=3.2.7)](https://search.maven.org/artifact/io.github.origin-energy/java-snapshot-testing-core/3.2.7/jar)
33

44
# Java Snapshot Testing
55
- Inspired by [facebook's Jest framework](https://facebook.github.io/jest/docs/en/snapshot-testing.html)
66

7-
🎉 3.X is live - parallel test support, easily override configuration via `snapshot.properties` yet *.snap format remains unchanged! This release will require some mechanical refactoring for those upgrading as `expect` is no longer a static method.
7+
🎉 4.0.0.Beta1 is live - We need testers
8+
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.origin-energy/java-snapshot-testing-core/badge.svg?subject=4.0.0-Beta1)](https://maven-badges.herokuapp.com/maven-central/io.github.origin-energy/java-snapshot-testing-core)
9+
- Report bugs to "Issues" clearly marking them as 4.0.0-Beta
810

9-
Upgrade guide from 2.X to 3.X [here](https://github.com/origin-energy/java-snapshot-testing/discussions/73)
11+
## Upgrading
12+
- Upgrade guild from 3.X to 4.X [here](https://github.com/origin-energy/java-snapshot-testing/discussions/94)
13+
- Upgrade guide from 2.X to 3.X [here](https://github.com/origin-energy/java-snapshot-testing/discussions/73)
1014

1115
## The testing framework loved by ~~lazy~~ __productive__ devs
1216

@@ -60,36 +64,36 @@ ci-env-var=CI
6064
```java
6165
package au.com.origin.snapshots.docs;
6266

67+
import au.com.origin.snapshots.Expect;
6368
import au.com.origin.snapshots.annotations.SnapshotName;
6469
import au.com.origin.snapshots.junit5.SnapshotExtension;
6570
import org.junit.jupiter.api.Test;
6671
import org.junit.jupiter.api.extension.ExtendWith;
6772

6873
import java.util.HashMap;
6974
import java.util.Map;
70-
import au.com.origin.snapshots.Expect;
7175

7276
@ExtendWith({SnapshotExtension.class})
7377
public class MyFirstSnapshotTest {
7478

75-
private Expect expect;
79+
private Expect expect;
7680

77-
@SnapshotName("i_can_give_custom_names_to_my_snapshots")
78-
@Test
79-
public void toStringSerializationTest() {
80-
expect.toMatchSnapshot("Hello World");
81-
}
81+
@SnapshotName("i_can_give_custom_names_to_my_snapshots")
82+
@Test
83+
public void toStringSerializationTest() {
84+
expect.toMatchSnapshot("Hello World");
85+
}
8286

83-
@Test
84-
public void jsonSerializationTest() {
85-
Map<String, Object> map = new HashMap<>();
86-
map.put("name", "John Doe");
87-
map.put("age", 40);
88-
89-
expect
90-
.serializer("json")
91-
.toMatchSnapshot(map);
92-
}
87+
@Test
88+
public void jsonSerializationTest() {
89+
Map<String, Object> map = new HashMap<>();
90+
map.put("name", "John Doe");
91+
map.put("age", 40);
92+
93+
expect
94+
.serializer("json")
95+
.toMatchSnapshot(map);
96+
}
9397

9498
}
9599
```
@@ -375,8 +379,8 @@ Here is a JUnit5 example that does not use the JUnit5 extension
375379
package au.com.origin.snapshots.docs;
376380

377381
import au.com.origin.snapshots.Expect;
378-
import au.com.origin.snapshots.PropertyResolvingSnapshotConfig;
379382
import au.com.origin.snapshots.SnapshotVerifier;
383+
import au.com.origin.snapshots.config.PropertyResolvingSnapshotConfig;
380384
import org.junit.jupiter.api.AfterAll;
381385
import org.junit.jupiter.api.BeforeAll;
382386
import org.junit.jupiter.api.Test;
@@ -385,23 +389,23 @@ import org.junit.jupiter.api.TestInfo;
385389
// Notice we aren't using any framework extensions
386390
public class CustomFrameworkExample {
387391

388-
private static SnapshotVerifier snapshotVerifier;
392+
private static SnapshotVerifier snapshotVerifier;
389393

390-
@BeforeAll
391-
static void beforeAll() {
392-
snapshotVerifier = new SnapshotVerifier(new PropertyResolvingSnapshotConfig(), CustomFrameworkExample.class);
393-
}
394+
@BeforeAll
395+
static void beforeAll() {
396+
snapshotVerifier = new SnapshotVerifier(new PropertyResolvingSnapshotConfig(), CustomFrameworkExample.class);
397+
}
394398

395-
@AfterAll
396-
static void afterAll() {
397-
snapshotVerifier.validateSnapshots();
398-
}
399+
@AfterAll
400+
static void afterAll() {
401+
snapshotVerifier.validateSnapshots();
402+
}
399403

400-
@Test
401-
void shouldMatchSnapshotOne(TestInfo testInfo) {
402-
Expect expect = Expect.of(snapshotVerifier, testInfo.getTestMethod().get());
403-
expect.toMatchSnapshot("Hello World");
404-
}
404+
@Test
405+
void shouldMatchSnapshotOne(TestInfo testInfo) {
406+
Expect expect = Expect.of(snapshotVerifier, testInfo.getTestMethod().get());
407+
expect.toMatchSnapshot("Hello World");
408+
}
405409

406410
}
407411
```
@@ -444,15 +448,17 @@ Often your IDE has an excellent file comparison tool.
444448

445449
This file allows you to conveniently setup global defaults
446450

447-
| key | Description |
448-
|------------------|----------------------------------------------------------------------------------------------------------------|
449-
|serializer | Class name of the [serializer](#supplying-a-custom-snapshotserializer), default serializer |
450-
|serializer.{name} | Class name of the [serializer](#supplying-a-custom-snapshotserializer), accessible via `.serializer("{name}")` |
451-
|comparator | Class name of the [comparator](#supplying-a-custom-snapshotcomparator) |
452-
|reporters | Comma separated list of class names to use as [reporters](#supplying-a-custom-snapshotreporter) |
453-
|snapshot-dir | Name of sub-folder holding your snapshots |
454-
|output-dir | Base directory of your test files (although it can be a different directory if you want) |
455-
|ci-env-var | Name of environment variable used to detect if we are running on a Build Server |
451+
| key | Description |
452+
|------------------|----------------------------------------------------------------------------------------------------------------------------------------|
453+
|serializer | Class name of the [serializer](#supplying-a-custom-snapshotserializer), default serializer |
454+
|serializer.{name} | Class name of the [serializer](#supplying-a-custom-snapshotserializer), accessible via `.serializer("{name}")` |
455+
|comparator | Class name of the [comparator](#supplying-a-custom-snapshotcomparator) |
456+
|comparator.{name} | Class name of the [comparator](#supplying-a-custom-snapshotcomparator), accessible via `.comparator("{name}")` |
457+
|reporters | Comma separated list of class names to use as [reporters](#supplying-a-custom-snapshotreporter) |
458+
|reporters.{name} | Comma separated list of class names to use as [reporters](#supplying-a-custom-snapshotreporter), accessible via `.reporters("{name}")` |
459+
|snapshot-dir | Name of sub-folder holding your snapshots |
460+
|output-dir | Base directory of your test files (although it can be a different directory if you want) |
461+
|ci-env-var | Name of environment variable used to detect if we are running on a Build Server |
456462

457463
For example:
458464

@@ -549,25 +555,27 @@ import org.junit.jupiter.api.extension.ExtendWith;
549555
@UseSnapshotConfig(LowercaseToStringSnapshotConfig.class)
550556
public class JUnit5ResolutionHierarchyExample {
551557

552-
@Test
553-
public void aliasMethodTest(Expect expect) {
554-
expect
555-
.serializer("json") // <------ Using snapshot.properties
556-
.toMatchSnapshot(new TestObject());
557-
}
558+
private Expect expect;
558559

559-
@Test
560-
public void customSerializerTest(Expect expect) {
561-
expect
562-
.serializer(UppercaseToStringSerializer.class) // <------ Using custom serializer
563-
.toMatchSnapshot(new TestObject());
564-
}
560+
@Test
561+
public void aliasMethodTest() {
562+
expect
563+
.serializer("json") // <------ Using snapshot.properties
564+
.toMatchSnapshot(new TestObject());
565+
}
565566

566-
// Read from LowercaseToStringSnapshotConfig defined on the class
567-
@Test
568-
public void lowercaseTest(Expect expect) {
569-
expect.toMatchSnapshot(new TestObject());
570-
}
567+
@Test
568+
public void customSerializerTest() {
569+
expect
570+
.serializer(UppercaseToStringSerializer.class) // <------ Using custom serializer
571+
.toMatchSnapshot(new TestObject());
572+
}
573+
574+
// Read from LowercaseToStringSnapshotConfig defined on the class
575+
@Test
576+
public void lowercaseTest() {
577+
expect.toMatchSnapshot(new TestObject());
578+
}
571579
}
572580
```
573581

@@ -588,39 +596,40 @@ import au.com.origin.snapshots.jackson.serializers.DeterministicJacksonSnapshotS
588596
import com.fasterxml.jackson.databind.ObjectMapper;
589597
import com.fasterxml.jackson.annotation.JsonIgnore;
590598
import com.fasterxml.jackson.annotation.JsonIgnoreType;
599+
import com.fasterxml.jackson.databind.ObjectMapper;
591600

592601
import java.time.Instant;
593602
import java.util.List;
594603
import java.util.Set;
595604

596605
public class HibernateSnapshotSerializer extends DeterministicJacksonSnapshotSerializer {
597606

598-
@Override
599-
public void configure(ObjectMapper objectMapper) {
600-
super.configure(objectMapper);
607+
@Override
608+
public void configure(ObjectMapper objectMapper) {
609+
super.configure(objectMapper);
601610

602-
// Ignore Hibernate Lists to prevent infinite recursion
603-
objectMapper.addMixIn(List.class, IgnoreTypeMixin.class);
604-
objectMapper.addMixIn(Set.class, IgnoreTypeMixin.class);
611+
// Ignore Hibernate Lists to prevent infinite recursion
612+
objectMapper.addMixIn(List.class, IgnoreTypeMixin.class);
613+
objectMapper.addMixIn(Set.class, IgnoreTypeMixin.class);
605614

606-
// Ignore Fields that Hibernate generates for us automatically
607-
objectMapper.addMixIn(BaseEntity.class, IgnoreHibernateEntityFields.class);
608-
}
615+
// Ignore Fields that Hibernate generates for us automatically
616+
objectMapper.addMixIn(BaseEntity.class, IgnoreHibernateEntityFields.class);
617+
}
609618

610-
@JsonIgnoreType
611-
class IgnoreTypeMixin {
612-
}
619+
@JsonIgnoreType
620+
class IgnoreTypeMixin {
621+
}
613622

614-
abstract class IgnoreHibernateEntityFields {
615-
@JsonIgnore
616-
abstract Long getId();
623+
abstract class IgnoreHibernateEntityFields {
624+
@JsonIgnore
625+
abstract Long getId();
617626

618-
@JsonIgnore
619-
abstract Instant getCreatedDate();
627+
@JsonIgnore
628+
abstract Instant getCreatedDate();
620629

621-
@JsonIgnore
622-
abstract Instant getLastModifiedDate();
623-
}
630+
@JsonIgnore
631+
abstract Instant getLastModifiedDate();
632+
}
624633
}
625634
```
626635

@@ -650,20 +659,21 @@ and field order are ignored.
650659
```java
651660
package au.com.origin.snapshots.docs;
652661

662+
import au.com.origin.snapshots.Snapshot;
653663
import au.com.origin.snapshots.comparators.SnapshotComparator;
654664
import com.fasterxml.jackson.databind.ObjectMapper;
655665
import lombok.SneakyThrows;
656666

657667
public class JsonObjectComparator implements SnapshotComparator {
658-
@Override
659-
public boolean matches(String snapshotName, String rawSnapshot, String currentObject) {
660-
return asObject(snapshotName, rawSnapshot).equals(asObject(snapshotName, currentObject));
661-
}
668+
@Override
669+
public boolean matches(Snapshot previous, Snapshot current) {
670+
return asObject(previous.getName(), previous.getBody()).equals(asObject(current.getName(), current.getBody()));
671+
}
662672

663-
@SneakyThrows
664-
private static Object asObject(String snapshotName, String json) {
665-
return new ObjectMapper().readValue(json.replaceFirst(snapshotName, ""), Object.class);
666-
}
673+
@SneakyThrows
674+
private static Object asObject(String snapshotName, String json) {
675+
return new ObjectMapper().readValue(json.replaceFirst(snapshotName + "=", ""), Object.class);
676+
}
667677
}
668678
```
669679

@@ -686,23 +696,24 @@ a custom reporter can be created like the one below.
686696
```java
687697
package au.com.origin.snapshots.docs;
688698

699+
import au.com.origin.snapshots.Snapshot;
689700
import au.com.origin.snapshots.reporters.SnapshotReporter;
690701
import au.com.origin.snapshots.serializers.SerializerType;
691702
import lombok.SneakyThrows;
692703
import org.skyscreamer.jsonassert.JSONAssert;
693704
import org.skyscreamer.jsonassert.JSONCompareMode;
694705

695706
public class JsonAssertReporter implements SnapshotReporter {
696-
@Override
697-
public boolean supportsFormat(String outputFormat) {
698-
return SerializerType.JSON.name().equalsIgnoreCase(outputFormat);
699-
}
707+
@Override
708+
public boolean supportsFormat(String outputFormat) {
709+
return SerializerType.JSON.name().equalsIgnoreCase(outputFormat);
710+
}
700711

701-
@Override
702-
@SneakyThrows
703-
public void report(String snapshotName, String rawSnapshot, String currentObject) {
704-
JSONAssert.assertEquals(rawSnapshot, currentObject, JSONCompareMode.STRICT);
705-
}
712+
@Override
713+
@SneakyThrows
714+
public void report(Snapshot previous, Snapshot current) {
715+
JSONAssert.assertEquals(previous.getBody(), current.getBody(), JSONCompareMode.STRICT);
716+
}
706717
}
707718
```
708719

@@ -722,14 +733,30 @@ import org.junit.jupiter.api.Test;
722733
import org.junit.jupiter.api.extension.ExtendWith;
723734

724735
@ExtendWith(SnapshotExtension.class)
725-
// apply your custom snapshot configuration to this test class
726736
@UseSnapshotConfig(LowercaseToStringSnapshotConfig.class)
727-
public class CustomSnapshotConfigExample {
737+
public class JUnit5ResolutionHierarchyExample {
728738

729-
@Test
730-
public void myTest(Expect expect) {
731-
expect.toMatchSnapshot("hello world");
732-
}
739+
private Expect expect;
740+
741+
@Test
742+
public void aliasMethodTest() {
743+
expect
744+
.serializer("json") // <------ Using snapshot.properties
745+
.toMatchSnapshot(new TestObject());
746+
}
747+
748+
@Test
749+
public void customSerializerTest() {
750+
expect
751+
.serializer(UppercaseToStringSerializer.class) // <------ Using custom serializer
752+
.toMatchSnapshot(new TestObject());
753+
}
754+
755+
// Read from LowercaseToStringSnapshotConfig defined on the class
756+
@Test
757+
public void lowercaseTest() {
758+
expect.toMatchSnapshot(new TestObject());
759+
}
733760
}
734761
```
735762

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
group=io.github.origin-energy
2-
version=3.4.0-SNAPSHOT
2+
version=4.0.0-Beta1-SNAPSHOT

0 commit comments

Comments
 (0)