typestar

test-suite.js en JavaScript

Un archivo de pruebas completo: suites, hooks, casos en tabla, mocks y tiempo simulado.

#!/usr/bin/env node --test
import { before, beforeEach, describe, it } from "node:test";
import assert from "node:assert/strict";

class Scorer {
  #history = [];

  constructor(target = 90) {
    if (target <= 0) throw new RangeError("target must be positive");
    this.target = target;
  }

  stars(tpm, accuracy) {
    if (accuracy < 0 || accuracy > 100) {
      throw new RangeError(`accuracy out of range: ${accuracy}`);
    }
    let earned = 1;
    if (accuracy >= 95) earned = 2;
    if (accuracy >= 98 && tpm >= this.target) earned = 3;
    this.#history.push(earned);
    return earned;
  }

  get best() {
    return this.#history.length ? Math.max(...this.#history) : 0;
  }

  async save(store) {
    return store.write(this.#history);
  }
}

describe("Scorer", () => {
  let scorer;

  before(() => assert.equal(typeof Scorer, "function"));
  beforeEach(() => { scorer = new Scorer(90); });

  describe("stars", () => {
    const cases = [
      { name: "slow but clean", tpm: 60, accuracy: 99, want: 2 },
      { name: "fast and clean", tpm: 95, accuracy: 99, want: 3 },
      { name: "fast and sloppy", tpm: 95, accuracy: 80, want: 1 },
      { name: "exactly at the bar", tpm: 90, accuracy: 98, want: 3 },
    ];

    for (const { name, tpm, accuracy, want } of cases) {
      it(name, () => assert.equal(scorer.stars(tpm, accuracy), want));
    }

    it("rejects an impossible accuracy", () => {
      assert.throws(() => scorer.stars(90, 140), {
        name: "RangeError",
        message: /out of range/,
      });
    });
  });

  describe("best", () => {
    it("is zero before any run", () => assert.equal(scorer.best, 0));

    it("keeps the highest", () => {
      scorer.stars(95, 99);
      scorer.stars(10, 50);
      assert.equal(scorer.best, 3);
    });
  });

  describe("save", () => {
    it("hands the history to the store", async (t) => {
      const write = t.mock.fn(async () => "written");
      scorer.stars(95, 99);

      assert.equal(await scorer.save({ write }), "written");
      assert.equal(write.mock.callCount(), 1);
      assert.deepEqual(write.mock.calls[0].arguments, [[3]]);
    });
  });

  it("refuses a zero target", () => {
    assert.throws(() => new Scorer(0), /positive/);
  });
});

Cómo funciona

  1. El código bajo prueba va arriba, así el archivo se sostiene solo.
  2. Los casos viven en un arreglo: agregar uno es una sola línea.
  3. Los mocks y los temporizadores simulados la mantienen rápida y determinista.

Palabras clave y builtins usados aquí

El intento, en números

Líneas
83
Caracteres a escribir
2000
Tokens
588
Ritmo de tres estrellas
110 tpm

Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 321 segundos.

Escribe este fragmento

Paso 1 de 1 en Bis; paso 9 de 9 en Pruebas con node:test.

← Anterior