test_test.dart 7.63 KB
Newer Older
1 2 3 4 5
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
6
import 'dart:io' as io;
7

8
import 'package:flutter_tools/src/base/file_system.dart';
9
import 'package:flutter_tools/src/base/io.dart';
10 11 12 13
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/dart/sdk.dart';
import 'package:test/test.dart';

14
import '../src/context.dart';
15 16 17

// This test depends on some files in ///dev/automated_tests/flutter_test/*

18 19
Future<Null> _testExclusionLock;

20
void main() {
21
  group('flutter test should', () {
22

23 24
    final String automatedTestsDirectory = fs.path.join('..', '..', 'dev', 'automated_tests');
    final String flutterTestDirectory = fs.path.join(automatedTestsDirectory, 'flutter_test');
25

26 27 28
    testUsingContext('not have extraneous error messages', () async {
      Cache.flutterRoot = '../..';
      return _testFile('trivial_widget', automatedTestsDirectory, flutterTestDirectory, exitCode: isZero);
29
    }, skip: io.Platform.isLinux); // Flutter on Linux sometimes has problems with font resolution (#7224)
30

31
    testUsingContext('report nice errors for exceptions thrown within testWidgets()', () async {
32 33
      Cache.flutterRoot = '../..';
      return _testFile('exception_handling', automatedTestsDirectory, flutterTestDirectory);
34
    }, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
35

36
    testUsingContext('report a nice error when a guarded function was called without await', () async {
37
      Cache.flutterRoot = '../..';
38
      return _testFile('test_async_utils_guarded', automatedTestsDirectory, flutterTestDirectory);
39
    }, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
40

41
    testUsingContext('report a nice error when an async function was called without await', () async {
42
      Cache.flutterRoot = '../..';
43
      return _testFile('test_async_utils_unguarded', automatedTestsDirectory, flutterTestDirectory);
44
    }, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
45

46 47 48
    testUsingContext('report a nice error when a Ticker is left running', () async {
      Cache.flutterRoot = '../..';
      return _testFile('ticker', automatedTestsDirectory, flutterTestDirectory);
49
    }, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
50

51
    testUsingContext('report a nice error when a pubspec.yaml is missing a flutter_test dependency', () async {
52
      final String missingDependencyTests = fs.path.join('..', '..', 'dev', 'missing_dependency_tests');
53
      Cache.flutterRoot = '../..';
54
      return _testFile('trivial', missingDependencyTests, missingDependencyTests);
55
    }, skip: io.Platform.isWindows); // Dart on Windows has trouble with unicode characters in output
56 57 58 59

    testUsingContext('run a test when its name matches a regexp', () async {
      Cache.flutterRoot = '../..';
      final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
60 61 62
        extraArgs: const <String>['--name', 'inc.*de']);
      if (!result.stdout.contains('+1: All tests passed'))
        fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
63 64 65 66 67 68
      expect(result.exitCode, 0);
    });

    testUsingContext('run a test when its name contains a string', () async {
      Cache.flutterRoot = '../..';
      final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
        extraArgs: const <String>['--plain-name', 'include']);
      if (!result.stdout.contains('+1: All tests passed'))
        fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
      expect(result.exitCode, 0);
    });

    testUsingContext('test runs to completion', () async {
      Cache.flutterRoot = '../..';
      final ProcessResult result = await _runFlutterTest('trivial', automatedTestsDirectory, flutterTestDirectory,
        extraArgs: const <String>['--verbose']);
      if ((!result.stdout.contains('+1: All tests passed')) ||
          (!result.stdout.contains('test 0: starting shell process')) ||
          (!result.stdout.contains('test 0: deleting temporary directory')) ||
          (!result.stdout.contains('test 0: finished')) ||
          (!result.stdout.contains('test package returned with exit code 0')))
        fail('unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n');
      if (result.stderr.isNotEmpty)
        fail('unexpected error output from test:\n\n${result.stderr}\n-- end stderr --\n\n');
87 88 89
      expect(result.exitCode, 0);
    });

90
  });
91 92
}

93 94
Future<Null> _testFile(String testName, String workingDirectory, String testDirectory, {Matcher exitCode}) async {
  exitCode ??= isNonZero;
95
  final String fullTestExpectation = fs.path.join(testDirectory, '${testName}_expectation.txt');
96
  final File expectationFile = fs.file(fullTestExpectation);
97
  if (!expectationFile.existsSync())
98
    fail('missing expectation file: $expectationFile');
99 100 101 102

  while (_testExclusionLock != null)
    await _testExclusionLock;

103
  final ProcessResult exec = await _runFlutterTest(testName, workingDirectory, testDirectory);
104

105
  expect(exec.exitCode, exitCode);
106
  final List<String> output = exec.stdout.split('\n');
107 108
  if (output.first == 'Waiting for another flutter command to release the startup lock...')
    output.removeAt(0);
109 110
  output.add('<<stderr>>');
  output.addAll(exec.stderr.split('\n'));
111
  final List<String> expectations = fs.file(fullTestExpectation).readAsLinesSync();
112 113 114
  bool allowSkip = false;
  int expectationLineNumber = 0;
  int outputLineNumber = 0;
115
  bool haveSeenStdErrMarker = false;
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
  while (expectationLineNumber < expectations.length) {
    expect(output, hasLength(greaterThan(outputLineNumber)));
    final String expectationLine = expectations[expectationLineNumber];
    final String outputLine = output[outputLineNumber];
    if (expectationLine == '<<skip until matching line>>') {
      allowSkip = true;
      expectationLineNumber += 1;
      continue;
    }
    if (allowSkip) {
      if (!new RegExp(expectationLine).hasMatch(outputLine)) {
        outputLineNumber += 1;
        continue;
      }
      allowSkip = false;
    }
132 133 134 135
    if (expectationLine == '<<stderr>>') {
      expect(haveSeenStdErrMarker, isFalse);
      haveSeenStdErrMarker = true;
    }
136
    expect(outputLine, matches(expectationLine), reason: 'Full output:\n- - - -----8<----- - - -\n${output.join("\n")}\n- - - -----8<----- - - -');
137 138 139 140
    expectationLineNumber += 1;
    outputLineNumber += 1;
  }
  expect(allowSkip, isFalse);
141 142
  if (!haveSeenStdErrMarker)
    expect(exec.stderr, '');
143
}
144

145 146 147 148
Future<ProcessResult> _runFlutterTest(
  String testName,
  String workingDirectory,
  String testDirectory, {
149
  List<String> extraArgs = const <String>[],
150 151
}) async {

152 153 154
  final String testFilePath = fs.path.join(testDirectory, '${testName}_test.dart');
  final File testFile = fs.file(testFilePath);
  if (!testFile.existsSync())
155
    fail('missing test file: $testFile');
156

157 158 159 160 161 162 163
  final List<String> args = <String>[]
    ..addAll(dartVmFlags)
    ..add(fs.path.absolute(fs.path.join('bin', 'flutter_tools.dart')))
    ..add('test')
    ..add('--no-color')
    ..addAll(extraArgs)
    ..add(testFilePath);
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

  while (_testExclusionLock != null)
    await _testExclusionLock;

  final Completer<Null> testExclusionCompleter = new Completer<Null>();
  _testExclusionLock = testExclusionCompleter.future;
  try {
    return await Process.run(
      fs.path.join(dartSdkPath, 'bin', 'dart'),
      args,
      workingDirectory: workingDirectory,
    );
  } finally {
    _testExclusionLock = null;
    testExclusionCompleter.complete();
  }
}