origin-energy / java-snapshot-testing

Facebook style snapshot testing for JAVA Tests
MIT License
109 stars 15 forks source link

Suggestion: include a YAML serializer #139

Open utluiz opened 1 year ago

utluiz commented 1 year ago

I have used snapshots for a while with jest and I'm really glad this library exists for Java. Snapshot-based assertions are very useful to make sure a data-processing system is consistently producing the correct output for a given input.

One of the most useful features of snapshots is being able to quickly spot when a specific value within a large payload has changed. Therefore, the output format matters a lot. However, JSON isn't always the most human-friendly format as it can be verbose with a lot of braces and commas that only get in the way.

So when I setup this library up in a new project of mine I wrote a custom serializer based on YAML, which I found to be the most clean and visually readable format among the common standard formats out there.

I think it could be a good addition having this shipped along with the jackson plugin.

Here's the code I came up with:

package org.example;

import au.com.origin.snapshots.Snapshot;
import au.com.origin.snapshots.SnapshotSerializerContext;
import au.com.origin.snapshots.exceptions.SnapshotExtensionException;
import au.com.origin.snapshots.serializers.SerializerType;
import au.com.origin.snapshots.serializers.SnapshotSerializer;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;

import java.util.Arrays;
import java.util.List;

public class JacksonYamlSnapshotSerializer implements SnapshotSerializer {
    private final ObjectMapper yamlMapper = new YAMLMapper()
            .enable(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE)
            .disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
            .enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID)
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
            .enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
            .setSerializationInclusion(JsonInclude.Include.NON_NULL);

    @Override
    public String getOutputFormat() {
        return "YAML";
    }

    @Override
    public Snapshot apply(final Object object, final SnapshotSerializerContext gen) {
        try {
            List<?> objects = Arrays.asList(object);
            return gen.toSnapshot("\n" + yamlMapper.writeValueAsString(objects));
        } catch (Exception e) {
            throw new SnapshotExtensionException("Yaml serialization failed", e);
        }
    }
}

A sample snapshot making use of that serializer looks like this:

org.example.ExampleTest.test2=
- foo: "foo2"
  bar: 2
jackmatt2 commented 1 year ago

I'd be happy for this to be added to java-snapshot-testing-jackson as an additional Serializer. Would you consider a PR?

Some comments: