Skip to content

4. Interpret results

After having defined your expectations as code and setting up DataConformance to run them against your database it is now time to take a look at the results. They are displayed on the Assertions page reachable from the top navigation.

Used data and definition
CREATE TABLE "public"."authors" ( 
"id" UUID NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "authors_pkey" PRIMARY KEY ("id")
);
CREATE TABLE "public"."posts" ( 
"id" UUID NOT NULL,
"name" TEXT NOT NULL,
"author_id" UUID NOT NULL,
CONSTRAINT "posts_pkey" PRIMARY KEY ("id")
);
INSERT INTO "public"."authors" ("id", "name") VALUES ('fb8bba38-ef1f-45d5-9438-20ca85f457a9', 'Bob Bobsson');
INSERT INTO "public"."authors" ("id", "name") VALUES ('32b7badd-e309-4e23-98b7-1b82898f3e01', 'Peter Petersson');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('83b4ad72-1474-4384-ae1d-27fb77d9cbd3', 'Hello World!', 'fb8bba38-ef1f-45d5-9438-20ca85f457a9');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('3b64b621-7fd9-4347-8aef-5512d50fb194', 'Hello World!', 'fb8bba38-ef1f-45d5-9438-20ca85f457a9');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('fdc38504-1fc8-4532-8d2d-f73c226dca0b', 'Learning to program', 'fb8bba38-ef1f-45d5-9438-20ca85f457a9');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('2e07738c-6b26-4c8b-982c-79b63507cde6', 'TDD is great', 'fb8bba38-ef1f-45d5-9438-20ca85f457a9');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('f618a74e-31c0-4822-88de-02d27f4af4b6', 'Setting up Jenkins', 'fb8bba38-ef1f-45d5-9438-20ca85f457a9');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('2ebc3794-1d5c-49cc-b17b-14d4357fc12b', 'Dealing with failing tests', '32b7badd-e309-4e23-98b7-1b82898f3e01');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('f7f4dd95-51b2-417f-822d-cac44fbfacb8', 'Defining non-functional requirements', '32b7badd-e309-4e23-98b7-1b82898f3e01');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('6b533d4d-3f5b-488b-82a2-a3c540f74245', 'Manage your project to success', '32b7badd-e309-4e23-98b7-1b82898f3e01');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('ec4e06d5-2eed-4aa1-845c-467ca7d848ba', 'Dealing with deadlines', '32b7badd-e309-4e23-98b7-1b82898f3e01');
INSERT INTO "public"."posts" ("id", "name", "author_id") VALUES ('d468ec76-2c3b-47b7-ae14-15e1155c0878', 'Sprint your way to the goal', '32b7badd-e309-4e23-98b7-1b82898f3e01');
ALTER TABLE "public"."posts" ADD CONSTRAINT "posts_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "public"."authors" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
using DataConformance.Checking;
using DataConformance.Checking.Constraints;
using DataConformance.Checking.Entities;

public class Post : Entity
{
    public override TableReference TableReference => new("posts");

    public override IReadOnlyCollection<ColumnReference>
        PrimaryKeyColumns => new[] { Id };

    public ColumnReference Id => ColumnReference.String(this, "id");

    public ColumnReference AuthorId => ColumnReference.String(this, "author_id");

    public ColumnReference Name => ColumnReference.String(this, "name");

    [Assertion]
    public Constraint AuthorsCanNotPublishTwoBlogPostsWithTheSameName()
    {
        return Check.For(Times.All, (Post postA) =>
            Check.For(Times.All, (Post postB) =>
                postA.IsNotEqualTo(postB)
                    .And(postA.AuthorId.IsEqualTo(postB.AuthorId))
                    .Implies(postA.Name.IsNotEqualTo(postB.Name))
            )
        );
    }
}

Awaiting first execution

Until an assertion has been executed it will show a message that it is awaiting first execution.

Assertion awaiting first execution

When your runner is up and running, then the assertion will be executed as part of the next run according to the schedule for the assigned definition. If you chose a manual schedule or don't want to wait until the next hour/day/week/month, you have the option to schedule an execution manually:

  1. Go to the page for your runner
  2. Click on the Schedule button next to the relevant assigned definition

It can still take up to ten minutes before your assertions are actually executed.

Successful assertion

When no data not matching the assertion is found it is marked as successful. You have nothing to do in this case.

Successful assertion

Failing assertion

When the assertion does not match reality it is marked as a failure. In this case it is up to you to determine if the data or your assertion is incorrect. To do this the result contains information about the involved entities.

Failed assertion

The assertion states that no two blog posts by the same author can have the same name, but this does not match the actual data. As you can see from the assertion execution result the two posts with ids 83b4ad72-1474-4384-ae1d-27fb77d9cbd3 and 3b64b621-7fd9-4347-8aef-5512d50fb194 share the same author id fb8bba38-ef1f-45d5-9438-20ca85f457a9 and the same name "Hello World!". Assuming that the assertion is correct the next action would be to decide how to fix the data.

Refining and adding assertions

As you find problems and evolve your application you will find the need to refine existing assertions and add new ones. Use every data-related problem not discovered via assertions as an invitation to reflect what assertions are missing and which part of your mental model of your database schema may be incorrect. Over time you will build up a library of assertions covering most of your database and letting you know about problems before your customers ever do.

If you have not already done so sign up and find those problems today!

Start 14-day Free Trial