top of page

Set Up Your Testing Environment — Hands-On Software Testing, Part 1

  • Shawn West
  • Jul 8
  • 3 min read

Updated: Aug 6

Hands-On Software Testing · Part 1

The reason people skip writing tests is rarely philosophical — it's friction. If running a test takes fifteen seconds and a context switch, you won't do it while you're in the middle of coding. This walks through setting up a testing environment where a test runs in a single keystroke, so testing becomes something you do continuously instead of something you schedule for later (and then don't).

Before writing a single test, you need a working test runner that's fast, gives clear output, and you trust. This tutorial walks through setting one up.

What You'll Build

A working test runner you can invoke with one command, that runs a placeholder test and reports clearly.

Step 1: Pick the Tool (5 min)

Common choices by language:

  • Python: pytest (default for most modern projects)

  • JavaScript/TypeScript: vitest or jest

  • Java: JUnit 5

  • C#/.NET: xUnit

  • Go: built-in testing package

  • Ruby: RSpec

Pick whatever's standard in your ecosystem. Don't overthink.

Step 2: Install (5 min)

Python:

pip install pytest

Node:

npm install --save-dev vitest

.NET:

dotnet new xunit -n YourProject.Tests

Install in a virtual env or contained context where possible.

Step 3: Configure (10 min)

pytestpytest.ini:

[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*

vitestvitest.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    include: ['**/*.test.ts'],
    environment: 'node',
  },
});

Configuration is mostly defaults at first. Don't over-configure.

Step 4: Write a Placeholder Test (5 min)

Pythontests/test_smoke.py:

def test_smoke():
    assert 1 + 1 == 2

TypeScriptsrc/smoke.test.ts:

import { test, expect } from 'vitest';

test('smoke test', () => {
  expect(1 + 1).toBe(2);
});

You're not testing your real code yet. You're verifying the test runner runs.

Step 5: Run It (2 min)

pytest        # or
npm test      # or
dotnet test

Expected output: 1 test passed.

If it doesn't work, fix it now. The test runner working is the foundation for everything.

Step 6: Make It Fast to Run (5 min)

The faster the runner, the more often you'll use it. Aim for <5 seconds startup.

  • Skip slow plugins you don't need

  • Configure parallel execution if available

  • Use watch mode for tight loops

pytest: pytest --tb=short -q (terse output during dev)

vitest: npx vitest --reporter=basic (faster reporter)

Step 7: Wire Up Your Editor (5 min)

VS Code: install the testing extension for your runner. Run individual tests with one click.

This dramatically increases how often you'll run tests.

Step 8: Add a "Test" Script (3 min)

Make running tests trivial:

Node — in package.json:

{
  "scripts": {
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:run": "vitest run"
  }
}

Python — in Makefile:

test:
	pytest

test-watch:
	pytest-watch

When the command is short, you run it more.

What You Just Did

You have a working test runner with a passing placeholder test. The infrastructure is now in place; the next tutorial writes a test that catches a real bug.

Time spent: 30 minutes. Worth it.

Common Failure Modes

Over-configuring at start. Adding plugins, custom reporters, etc. before you've written tests. Keep it minimal.

Slow runner. Multi-second startup. Investigate; fast feedback matters.

No watch mode. Running tests manually every change. Use watch mode during development.

Different runners in different contexts. Local uses X, CI uses Y. Same runner everywhere; CI is just non-interactive.

Continue the Hands-On Software Testing path

Part of the Hands-On Software Testing learning path.

bottom of page