Keep logic within tests for as long as you can

Inspired by some recent podcast guests, I've started writing the first code for a Drupal-based SaaS product that I've been thinking of creating.

Here's an early iteration of the first test I wrote:

public function test_it_creates_a_project_node_from_json(): void {
  self::assertNull(Node::load(id: 1));

  $this->installEntitySchema(entity_type_id: 'node');
  $this->installConfig(modules: self::$modules);

  $projectData = json_decode(json: self::$projectJson, associative: TRUE);
  self::assertNotNull($projectData);

  Node::create([
    'title' => $projectData['list'][0]['title'],
    'type' => 'drupal_project',
  ])->save();

  $node = Node::load(id: 1);

  self::assertNotNull($node);
  self::assertInstanceOf(actual: $node, expected: NodeInterface::class);
  self::assertSame(actual: $node->label(), expected: 'Override Node Options');

  self::assertSame(
    actual: $node->get('field_drupalorg_node_id')->getString(),
    expected: strval(107871),
  );
}

It checks that, given some defined JSON data, it will create a node in my database.

It confirms no node ID exists when starting, runs some setup setups (this is a Kernel test), decodes the JSON, creates the node and asserts it contains the expected values.

There are two things that you may be wondering...

  • Why do you have test setup code that you'll need within the test? Won't you need that for every test?
  • Why are you creating the node within the test and not somewhere else?

The answer to both is that this is the first test, and I want to write as little code as possible for it to pass.

When I write the second test, I'll either need to duplicate the setup lines or extract them to a setUp() method.

I'll also need to refactor the code that creates the node.

Once I've written the second test, to get it to pass, I refactored to use Repository, Builder and Action classes.

If there's a regression, the test I had will fail, and I could revert to the passing version before reattempting the refactor.

With test-driven development, I want to work in small and simple steps and get to green by making the smallest and easiest possible change.

When I have a test that forces me to refactor and adopt a more complex approach, I'll do it.

- Oliver

Was this interesting?

Sign up here and get more like this delivered straight to your inbox every day.

About me

Picture of Oliver

I'm an Acquia-certified Drupal Triple Expert with 17 years of experience, an open-source software maintainer and Drupal core contributor, public speaker, live streamer, and host of the Beyond Blocks podcast.