NSWI142: Web Applications

Testing

Preliminaries

Please read this section at least one day prior to the seminar. This section outlines what you are expected to know, be able to do, or prepare in advance. Following these instructions will help you get the most out of the seminar and ensure smooth participation.

Preliminaries

Before the start of the practical, you should be able to:

  • Run JavaScript using NodeJS.
  • Run a PHP script.
  • Explain the Model-View-Presenter design pattern.

Preliminaries software

This slide applies to you only if you plan to use your own computer for the practical.

Before the start of the practical, make sure that:

  • You can run php commands from a command line.
  • You have PHPUnit installed.
  • You can run phpunit commands from command line.
  • You have NodeJS version 24 (or higher) installed.
  • An IDE with support for JavaScript would be nice.

Exercise: Software testing

For more see Software Testing - NTIN070 or Advanced Programming of Web Applications - NSWI153.

Why, what and when?

Try to find answers to following questions:

  • What is a test?
  • Have you seen or interacted with any tests so far?
  • When you should test?
  • Should you always test?
  • What types of tests do you know?

How?

...

Demonstration: PHPUnit

Simple test ...

The test file must contain a class matching the file name. A class method which name starts with "test" defines a test.


      <?php

      use PHPUnit\Framework\TestCase;

      final class SimpleTest extends TestCase
      {
          public function testAddition(): void
          {
              $this->assertSame(2, 1 + 1);
          }
      }
    

Search and run all "*Test.php" files in tests directory (and subdirecories):


      phpunit ./tests
    

Demonstration: node:test

The node:test is part of NodeJS modules. While usually not the first choice, it can get the job done.

Simple test ...

Content of simple.test.js file:


      import assert from "node:assert";
      import test from "node:test";

      test("Test addition.", () => {
        const actual = 1 + 1;
        const expected = 2;
        assert.strictEqual(actual, expected);
      });
    

Search for test files in this and subdirectories (e.g. test-feature.js, feature.test.js, ...):


      node --test
    

We can also use --watch to watch for file changes.

JavaScript modules

In order to write a test for JS functionality, we need to be able to export and import classes, functions, and variables. In the following example, we create a simple.js file that exports function add.

Content of simple.js file:


      function add(left, right) {
        return left + right;
      }
      // module.exports = { add };
      export { add };
    

Content of simple.test.js file:


      import assert from "node:assert";
      import test from "node:test";

      import { add } from "./simple.js";

      test("Test addition.", () => {
        const actual = add(1, 1);
        const expected = 2;
        assert.strictEqual(actual, expected);
      });
    

Grouping tests together

We can groups tests into suites. In the following example, "suite" can be replaced with "describe" and "test" can be replaced with "it".


      import assert from "node:assert";
      import { suite, test } from "node:test";

      import { add } from "./simple.js";

      suite("add", () => {

        test("Add zeros.", () => {
          const actual = add(0, 0);
          assert.strictEqual(actual, 0);
        });

        test("Add negative.", () => {
          const actual = add(1, -1);
          assert.strictEqual(actual, 0);
        });

      });
    

Exercise: Testing a presenter

The functionality

Functionality is based on the previous exercises (a simple product list with filtering). The objective is to design and implement tests for the presenter. It should support the following UI elements and functionality:

  • Text search - a text input element.
  • Slider to set maximum price - a number input element with name.
  • Checkbox to show only items from the garden category.
  • A button that will clear all filters.
  • A combobox to select item ordering. Following orderings has to be available: label ascending, label descending, price ascending, price descending.

Think about the presenter:

  • Should it be a class or a function?
  • What behavior/methods should the presenter expose?
  • Can you write documentation strings for them?

Continue to the next slide once you are done.

Model-View-Presenter

In order to test the Presenter, you may need to have a View or a Model. If so, just create a mock implementation.

Aim to write as little code as possible outside the test file.

Continue to the next slide once you are done.

Implementation

Implementation is coming.

Continue to the next slide once you are done.

Task Complete

Congratulations, if you have followed the instructions, you have just reached the end of this exercise.

Questions, ideas, or any other feedback?

Please feel free to use the anonymous feedback form.