Dart testing Command line program

Viewed 230

Suppose I have the following program increment.dart,

import 'dart:io';

void main() {
  var input = int.parse(stdin.readLineSync());
  print(++input);
}

and I want to test it similar to expect() from test package like,

test('Increment', () {
  expect(/*call program with input 0*/ , equals(1));
});

Elaborating my use case:

I use this website to practice by solving the puzzles. They do have an online IDE but it doesn't have any debugging tools and the programs use std io. So what I have to do for debugging my code locally is to replace every stdin.readLineSync() with hardcoded test values and then repeat for every test. I'm looking a way to automate this.(Much like how things work on their site)

1 Answers

Following @jamesdlin's suggestion, I looked up info about Processes and found this example and whipped up the following test:

@TestOn('vm')

import 'dart:convert';
import 'dart:io';

import 'package:test/test.dart';

void main() {
  test('Increment 0', () async {
    final input = 0;
    final path = 'increment.dart';
    final process = await Process.start('dart', ['$path']);

    // Send input to increment.dart's stdin.
    process.stdin.writeln(input);

    final lineStream =
        process.stdout.transform(Utf8Decoder()).transform(LineSplitter());
    
    // Test output of increment.dart
    expect(
        lineStream,
        emitsInOrder([
          // Values match individual events.
          '${input + 1}',

          // By default, more events are allowed after the matcher finishes
          // matching. This asserts instead that the stream emits a done event and
          // nothing else.
          emitsDone
        ]));
  });
}

Trivia:

Used to specify a Platform Selector.

Used to run commands from the program itself like, ls -l (code: Process.start('ls', ['-l'])). First argument takes the command to be executed and second argument takes the list of arguments to be passed.

Related