Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Dart Dictionary

  1. Home
  2. Dart Dictionary
  3. Unit Testing (test() / expect() / group())

Unit Testing (test() / expect() / group())

The dart:test package provides a standard testing framework for writing and running unit tests in Dart. You define test cases with the test() function and write assertions with expect(). Running dart test executes your tests, letting you develop with confidence.

Syntax

// Import the package
import 'package:test/test.dart';

// test(): defines a single test case
test('test name', () {
  // Write the test body here
  expect(actualValue, matcher);
});

// group(): groups related tests together
group('group name', () {
  setUp(() {
    // Initialization code that runs before each test
  });

  tearDown(() {
    // Cleanup code that runs after each test
  });

  test('test name', () {
    expect(actualValue, matcher);
  });
});

// Commonly used matchers
expect(value, equals(expected));          // Check for equality
expect(value, isTrue);                    // Check that value is true
expect(value, isFalse);                   // Check that value is false
expect(value, isNull);                    // Check that value is null
expect(value, isNotNull);                 // Check that value is not null
expect(value, isA<Type>());              // Check the type
expect(value, contains('string'));        // Check that a string or collection contains an element
expect(value, hasLength(n));             // Check the length
expect(value, greaterThan(n));           // Check that value is greater than n
expect(value, lessThan(n));              // Check that value is less than n
expect(value, throwsA(isA<Exception>())); // Check that an exception is thrown
expect(() => fn(), throwsException);     // Check that any exception is thrown

Syntax Reference

Function / MatcherDescription
test(name, body)Defines a single test case. Pass a string describing the test as name and the test logic as body.
group(name, body)Groups related tests together. The group name is prepended to each test name in the output.
setUp(fn)Registers a setup function that runs before each test. Use it to initialize state for every test.
tearDown(fn)Registers a cleanup function that runs after each test. Use it to release resources.
setUpAll(fn)Runs once before all tests in a group. Use it for expensive initialization that only needs to happen once.
tearDownAll(fn)Runs once after all tests in a group have completed.
expect(actual, matcher)Verifies that the actual value satisfies the matcher condition. The test fails if the condition is not met.
equals(expected)A matcher that verifies the value is equal to expected.
isTrue / isFalseMatchers that verify the value is true or false.
isNull / isNotNullMatchers that verify the value is null or not null.
isA<T>()A matcher that verifies the value is an instance of type T.
contains(value)A matcher that verifies a string or collection contains the specified element.
hasLength(n)A matcher that verifies a string or collection has a length of n.
greaterThan(n) / lessThan(n)Matchers that verify the value is greater than or less than n.
throwsA(matcher)A matcher that verifies a function throws an exception matching the given matcher.
throwsExceptionA matcher that verifies a function throws any Exception.
throwsArgumentErrorA matcher that verifies a function throws an ArgumentError.

Sample Code

jjk_sorcerer_test.dart
// jjk_sorcerer_test.dart — sample demonstrating basic dart:test usage
// Uses a sorcerer class from Jujutsu Kaisen as the subject under test

import 'package:test/test.dart';

// -----------------------------------------------
// Class definitions for the subject under test
// -----------------------------------------------

// Enum representing a sorcerer's grade
enum SorcererGrade { special, first, second, third, fourth }

// Sorcerer class
class Sorcerer {
  final String        name;
  final SorcererGrade grade;
  final String        technique;
  int                 cursedEnergy; // Mutable value that changes over time

  Sorcerer({
    required this.name,
    required this.grade,
    required this.technique,
    required this.cursedEnergy,
  });

  // Activates a technique. Consumes cursed energy and returns a result string.
  String activate(int cost) {
    if (cost <= 0) {
      throw ArgumentError('Activation cost must be 1 or greater');
    }
    if (cursedEnergy < cost) {
      throw StateError('Not enough cursed energy (required: $cost, remaining: $cursedEnergy)');
    }
    cursedEnergy -= cost;
    return '${name} activated ${technique} (remaining energy: $cursedEnergy)';
  }

  // Restores cursed energy
  void recover(int amount) {
    if (amount <= 0) {
      throw ArgumentError('Recovery amount must be 1 or greater');
    }
    cursedEnergy += amount;
  }

  // Returns true if the sorcerer is special grade
  bool get isSpecialGrade => grade == SorcererGrade.special;

  // Returns a string representation of the sorcerer
  @override
  String toString() => '$name (${grade.name}): $technique';
}

// Sorcerer team class
class SorcererTeam {
  final String         teamName;
  final List<Sorcerer> members;

  SorcererTeam({required this.teamName, required this.members});

  // Returns the total cursed energy of all members
  int get totalCursedEnergy =>
      members.fold(0, (sum, s) => sum + s.cursedEnergy);

  // Returns a list of special-grade members
  List<Sorcerer> get specialGradeMembers =>
      members.where((s) => s.isSpecialGrade).toList();

  // Finds a member by name. Returns null if not found.
  Sorcerer? findByName(String name) {
    try {
      return members.firstWhere((s) => s.name == name);
    } catch (_) {
      return null;
    }
  }
}

// -----------------------------------------------
// Test code
// -----------------------------------------------

void main() {
  // -----------------------------------------------
  // Tests for the Sorcerer class
  // -----------------------------------------------
  group('Sorcerer class', () {
    // Initialize sorcerer instances before each test
    late Sorcerer gojo;
    late Sorcerer itadori;
    late Sorcerer nobara;

    setUp(() {
      // setUp runs before each test, ensuring a fresh state every time
      gojo    = Sorcerer(name: '五条悟',    grade: SorcererGrade.special, technique: '無下限呪術', cursedEnergy: 9999);
      itadori = Sorcerer(name: '虎杖悠仁',  grade: SorcererGrade.first,   technique: '発勁',       cursedEnergy: 500);
      nobara  = Sorcerer(name: '釘崎野薔薇', grade: SorcererGrade.third,   technique: '芻霊呪法',   cursedEnergy: 300);
    });

    // --- Test using the equals matcher ---
    test('name property is set correctly', () {
      expect(gojo.name,    equals('五条悟'));
      expect(itadori.name, equals('虎杖悠仁'));
      expect(nobara.name,  equals('釘崎野薔薇'));
    });

    // --- Test using the isTrue / isFalse matchers ---
    test('isSpecialGrade returns the correct value', () {
      expect(gojo.isSpecialGrade,    isTrue);  // 五条悟 is special grade
      expect(itadori.isSpecialGrade, isFalse); // 虎杖悠仁 is not special grade
    });

    // --- Test for state changes ---
    test('activate() consumes cursed energy correctly', () {
      var result = itadori.activate(100);
      // Check remaining energy after consumption
      expect(itadori.cursedEnergy, equals(400));
      // Check that the return value contains the sorcerer name and technique
      expect(result, contains('虎杖悠仁'));
      expect(result, contains('発勁'));
    });

    test('recover() restores cursed energy correctly', () {
      nobara.recover(200);
      expect(nobara.cursedEnergy, equals(500));
    });

    // --- Test using greaterThan / lessThan matchers ---
    test('五条悟 has more cursed energy than 虎杖悠仁', () {
      expect(gojo.cursedEnergy, greaterThan(itadori.cursedEnergy));
      expect(nobara.cursedEnergy, lessThan(itadori.cursedEnergy));
    });

    // --- Exception tests ---
    group('activate() exception tests', () {
      test('throws ArgumentError when cost is 0 or less', () {
        // Use throwsA and isA to check the type of the thrown exception
        expect(
          () => itadori.activate(0),
          throwsA(isA<ArgumentError>()),
        );
      });

      test('throws StateError when cursed energy is insufficient', () {
        expect(
          () => nobara.activate(9999), // Only has 300 energy but requests 9999
          throwsA(isA<StateError>()),
        );
      });

      test('recover() throws ArgumentError when amount is 0 or less', () {
        // throwsArgumentError is a convenient shorthand matcher
        expect(() => gojo.recover(-1), throwsArgumentError);
      });
    });

    // --- Test for toString ---
    test('toString() returns the correct format', () {
      var str = gojo.toString();
      // Use isA to check the type
      expect(str, isA<String>());
      expect(str, contains('五条悟'));
      expect(str, contains('無下限呪術'));
    });
  });

  // -----------------------------------------------
  // Tests for the SorcererTeam class
  // -----------------------------------------------
  group('SorcererTeam class', () {
    late SorcererTeam team;

    // setUpAll runs once for the entire group
    setUpAll(() {
      print('Setting up SorcererTeam tests');
    });

    setUp(() {
      // Initialize the team before each test
      team = SorcererTeam(
        teamName: 'Tokyo School Selection Team',
        members: [
          Sorcerer(name: '五条悟',    grade: SorcererGrade.special, technique: '無下限呪術', cursedEnergy: 9999),
          Sorcerer(name: '虎杖悠仁',  grade: SorcererGrade.first,   technique: '発勁',       cursedEnergy: 500),
          Sorcerer(name: '釘崎野薔薇', grade: SorcererGrade.third,   technique: '芻霊呪法',   cursedEnergy: 300),
          Sorcerer(name: '伏黒恵',    grade: SorcererGrade.first,   technique: '十種影法術', cursedEnergy: 600),
        ],
      );
    });

    tearDownAll(() {
      print('SorcererTeam tests complete');
    });

    // --- Test using the hasLength matcher ---
    test('team has 4 members', () {
      expect(team.members, hasLength(4));
    });

    // --- Test using isNotNull / isNull matchers ---
    test('findByName() finds an existing member', () {
      var found = team.findByName('伏黒恵');
      expect(found, isNotNull);
      expect(found!.technique, equals('十種影法術'));
    });

    test('findByName() returns null for a non-existent member', () {
      var notFound = team.findByName('夏油傑');
      expect(notFound, isNull);
    });

    // --- Tests for collection matchers ---
    test('specialGradeMembers contains only 五条悟', () {
      var specials = team.specialGradeMembers;
      expect(specials, hasLength(1));
      expect(specials.first.name, equals('五条悟'));
    });

    test('totalCursedEnergy matches the sum of all members', () {
      // 9999 + 500 + 300 + 600 = 11399
      expect(team.totalCursedEnergy, equals(11399));
    });
  });
}
dart test jjk_sorcerer_test.dart
Building package executable...
Built test:test.
00:02 +12: All tests passed!

Overview

Dart's testing framework is provided by package:test/test.dart. Use test() to define individual test cases and group() to organize related tests. setUp() and tearDown() run initialization and cleanup code around each test, while setUpAll() and tearDownAll() run once for the entire group. Write assertions using expect() combined with matchers such as equals, isTrue, isNull, isA<T>(), contains, and throwsA. Run your tests with dart test filename.dart; all passing tests produce the message All tests passed!. For details on exception handling, see Exception Handling (try / catch / throw). For asynchronous testing, see async / await.

If you find any errors or copyright issues, please .