Skip to content

Commit a86cd9b

Browse files
authored
Enhance coverage to cover all appropriate binary-level tests (#1879)
* Cleanup and move test-only code into the test utils library * Fix coverage for binary-level tests * dartfmt * Adjust timeout factor * Unconditionally add coverage path environment variable * Move main up to the top; coverage runs take a bit more time
1 parent 04ed8ec commit a86cd9b

File tree

7 files changed

+156
-111
lines changed

7 files changed

+156
-111
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ dart:
44
- stable
55
- "dev/raw/latest"
66
env:
7+
- DARTDOC_BOT=main
78
- DARTDOC_BOT=flutter
89
- DARTDOC_BOT=sdk-analyzer
9-
- DARTDOC_BOT=main
1010
- DARTDOC_BOT=packages
1111
- DARTDOC_BOT=sdk-docs
1212
script: ./tool/travis.sh

lib/src/io_utils.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ final libraryNameRegexp = new RegExp('[.:]');
8080
final partOfRegexp = new RegExp('part of ');
8181
final newLinePartOfRegexp = new RegExp('\npart of ');
8282

83-
8483
/// Best used with Future<void>.
8584
class MultiFutureTracker<T> {
8685
/// Approximate maximum number of simultaneous active Futures.
@@ -113,5 +112,3 @@ class MultiFutureTracker<T> {
113112
/// Wait until all futures added so far have completed.
114113
Future<void> wait() async => await _waitUntil(0);
115114
}
116-
117-

lib/src/model.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ class Accessor extends ModelElement implements EnclosedElement {
464464
@override
465465
void warn(PackageWarning kind,
466466
{String message,
467-
Iterable<Locatable> referredFrom,
468-
Iterable<String> extendedDebug}) {
467+
Iterable<Locatable> referredFrom,
468+
Iterable<String> extendedDebug}) {
469469
enclosingCombo.warn(kind,
470470
message: message,
471471
referredFrom: referredFrom,
@@ -2031,7 +2031,8 @@ abstract class GetterSetterCombo implements ModelElement {
20312031
if (writeOnly) return r'&#8592;';
20322032
// ↔
20332033
if (readWrite) return r'&#8596;';
2034-
throw UnsupportedError('GetterSetterCombo must be one of readOnly, writeOnly, or readWrite');
2034+
throw UnsupportedError(
2035+
'GetterSetterCombo must be one of readOnly, writeOnly, or readWrite');
20352036
}
20362037

20372038
bool get readOnly => hasPublicGetter && !hasPublicSetter;

test/compare_output_test.dart

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import 'package:dartdoc/src/package_meta.dart';
1212
import 'package:path/path.dart' as pathLib;
1313
import 'package:test/test.dart';
1414

15+
import 'src/utils.dart';
16+
1517
const List<String> _filesToIgnore = const <String>['.DS_Store'];
1618

1719
const String gitBinName = 'git';
@@ -40,10 +42,20 @@ String get _testPackageFlutterPluginPath => pathLib
4042
void main() {
4143
group('compare outputs', () {
4244
Directory tempDir;
45+
CoverageSubprocessLauncher subprocessLauncher;
4346

4447
var dartdocBin =
4548
pathLib.fromUri(_currentFileUri.resolve('../bin/dartdoc.dart'));
4649

50+
setUpAll(() {
51+
subprocessLauncher =
52+
new CoverageSubprocessLauncher('compare_output_test-subprocesses');
53+
});
54+
55+
tearDownAll(() async {
56+
await Future.wait(CoverageSubprocessLauncher.coverageResults);
57+
});
58+
4759
setUp(() {
4860
tempDir = Directory.systemTemp.createTempSync('dartdoc.test.');
4961
});
@@ -55,27 +67,38 @@ void main() {
5567
});
5668

5769
test('Validate missing FLUTTER_ROOT exception is clean', () async {
70+
StringBuffer output = new StringBuffer();
5871
var args = <String>[dartdocBin];
59-
var result = Process.runSync(Platform.resolvedExecutable, args,
72+
Future run = subprocessLauncher.runStreamed(
73+
Platform.resolvedExecutable, args,
6074
environment: new Map.from(Platform.environment)
6175
..remove('FLUTTER_ROOT'),
6276
includeParentEnvironment: false,
63-
workingDirectory: _testPackageFlutterPluginPath);
77+
workingDirectory: _testPackageFlutterPluginPath, perLine: (s) {
78+
output.writeln(s);
79+
});
80+
// Asynchronous exception, but we still need the output, too.
81+
expect(run, throwsA(new TypeMatcher<ProcessException>()));
82+
try {
83+
await run;
84+
} on ProcessException catch (_) {}
85+
6486
expect(
65-
result.stderr,
87+
output.toString(),
6688
contains(new RegExp(
6789
'Top level package requires Flutter but FLUTTER_ROOT environment variable not set|test_package_flutter_plugin requires the Flutter SDK, version solving failed')));
68-
expect(result.stderr, isNot(contains('asynchronous gap')));
69-
expect(result.exitCode, isNot(0));
90+
expect(output.toString(), isNot(contains('asynchronous gap')));
7091
});
7192

7293
test("Validate --version works", () async {
94+
StringBuffer output = new StringBuffer();
7395
var args = <String>[dartdocBin, '--version'];
74-
var result = Process.runSync(Platform.resolvedExecutable, args,
75-
workingDirectory: _testPackagePath);
96+
await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
97+
workingDirectory: _testPackagePath,
98+
perLine: (s) => output.writeln(s));
7699
PackageMeta dartdocMeta = new PackageMeta.fromFilename(dartdocBin);
77-
expect(
78-
result.stdout, equals('dartdoc version: ${dartdocMeta.version}\n'));
100+
expect(output.toString(),
101+
endsWith('dartdoc version: ${dartdocMeta.version}\n'));
79102
});
80103

81104
test("Validate html output of test_package", () async {
@@ -100,6 +123,8 @@ void main() {
100123
'--pretty-index-json',
101124
];
102125

126+
// Deliberately use runSync here to avoid counting this test as
127+
// "test coverage".
103128
var result = Process.runSync(Platform.resolvedExecutable, args,
104129
workingDirectory: _testPackagePath);
105130

@@ -157,7 +182,8 @@ void main() {
157182
fail(message.join('\n'));
158183
});
159184

160-
test('Check for sample code in examples', () {
185+
test('Check for sample code in examples', () async {
186+
StringBuffer output = new StringBuffer();
161187
var args = <String>[
162188
dartdocBin,
163189
'--include',
@@ -167,28 +193,21 @@ void main() {
167193
tempDir.path
168194
];
169195

170-
var result = Process.runSync(Platform.resolvedExecutable, args,
171-
workingDirectory: _testPackagePath);
172-
173-
if (result.exitCode != 0) {
174-
print(result.exitCode);
175-
print(result.stdout);
176-
print(result.stderr);
177-
fail('dartdoc failed');
178-
}
196+
await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
197+
workingDirectory: _testPackagePath,
198+
perLine: (s) => output.writeln(s));
179199

180200
// Examples are reported as unfound because we (purposefully)
181201
// did not use --example-path-prefix above.
182202
final sep = '.'; // We don't care what the path separator character is
183203
final firstUnfoundExample = new RegExp('warning: lib${sep}example.dart: '
184204
'@example file not found.*test_package${sep}dog${sep}food.md');
185-
if (!result.stderr.contains(firstUnfoundExample)) {
186-
fail('Should warn about unfound @example files: \n'
187-
'stdout:\n${result.stdout}\nstderr:\n${result.stderr}');
205+
if (!output.toString().contains(firstUnfoundExample)) {
206+
fail('Should warn about unfound @example files');
188207
}
189208
});
190209

191-
test('Validate JSON output', () {
210+
test('Validate JSON output', () async {
192211
var args = <String>[
193212
dartdocBin,
194213
'--include',
@@ -199,28 +218,15 @@ void main() {
199218
'--json'
200219
];
201220

202-
var result = Process.runSync(Platform.resolvedExecutable, args,
221+
Iterable<Map> jsonValues = await subprocessLauncher.runStreamed(
222+
Platform.resolvedExecutable, args,
203223
workingDirectory: _testPackagePath);
204224

205-
if (result.exitCode != 0) {
206-
print(result.exitCode);
207-
print(result.stdout);
208-
print(result.stderr);
209-
fail('dartdoc failed');
210-
}
211-
212-
var jsonValues = LineSplitter.split(result.stdout)
213-
.map((j) => json.decode(j) as Map<String, dynamic>)
214-
.toList();
215-
216225
expect(jsonValues, isNotEmpty,
217226
reason: 'All STDOUT lines should be JSON-encoded maps.');
227+
}, timeout: new Timeout.factor(2));
218228

219-
expect(result.stderr as String, isEmpty,
220-
reason: 'STDERR should be empty.');
221-
});
222-
223-
test('--footer-text includes text', () {
229+
test('--footer-text includes text', () async {
224230
String footerTextPath =
225231
pathLib.join(Directory.systemTemp.path, 'footer.txt');
226232
new File(footerTextPath).writeAsStringSync(' footer text include ');
@@ -234,20 +240,15 @@ void main() {
234240
tempDir.path
235241
];
236242

237-
var result = Process.runSync(Platform.resolvedExecutable, args,
243+
await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
238244
workingDirectory: _testPackagePath);
239245

240-
if (result.exitCode != 0) {
241-
print(result.exitCode);
242-
print(result.stdout);
243-
print(result.stderr);
244-
fail('dartdoc failed');
245-
}
246-
247246
File outFile = new File(pathLib.join(tempDir.path, 'index.html'));
248247
expect(outFile.readAsStringSync(), contains('footer text include'));
249248
});
250-
}, onPlatform: {'windows': new Skip('Avoiding parsing git output')});
249+
},
250+
onPlatform: {'windows': new Skip('Avoiding parsing git output')},
251+
timeout: new Timeout.factor(3));
251252
}
252253

253254
Map<String, String> _parseOutput(

test/dartdoc_test.dart

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ void main() {
2727
group('dartdoc with generators', () {
2828
Directory tempDir;
2929
List<String> outputParam;
30+
CoverageSubprocessLauncher subprocessLauncher;
31+
3032
setUpAll(() async {
33+
subprocessLauncher =
34+
new CoverageSubprocessLauncher('dartdoc_test-subprocesses');
3135
tempDir = Directory.systemTemp.createTempSync('dartdoc.test.');
3236
outputParam = ['--output', tempDir.path];
3337
DartdocOptionSet optionSet = await DartdocOptionSet.fromOptionGenerators(
@@ -38,6 +42,7 @@ void main() {
3842
});
3943

4044
tearDown(() async {
45+
await Future.wait(CoverageSubprocessLauncher.coverageResults);
4146
tempDir.listSync().forEach((FileSystemEntity f) {
4247
f.deleteSync(recursive: true);
4348
});
@@ -112,21 +117,24 @@ void main() {
112117
String dartdocPath = pathLib.join('bin', 'dartdoc.dart');
113118

114119
test('errors cause non-zero exit when warnings are off', () async {
115-
ProcessResult result = Process.runSync(Platform.resolvedExecutable, [
116-
dartdocPath,
117-
'--input=$testPackageToolError',
118-
'--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}',
119-
]);
120-
expect(result.exitCode, isNonZero);
120+
expect(
121+
() => subprocessLauncher.runStreamed(Platform.resolvedExecutable, [
122+
dartdocPath,
123+
'--input=${testPackageToolError.path}',
124+
'--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}'
125+
]),
126+
throwsA(const TypeMatcher<ProcessException>()));
121127
});
128+
122129
test('errors cause non-zero exit when warnings are on', () async {
123-
ProcessResult result = Process.runSync(Platform.resolvedExecutable, [
124-
dartdocPath,
125-
'--input=$testPackageToolError',
126-
'--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}',
127-
'--show-warnings',
128-
]);
129-
expect(result.exitCode, isNonZero);
130+
expect(
131+
() => subprocessLauncher.runStreamed(Platform.resolvedExecutable, [
132+
dartdocPath,
133+
'--input=${testPackageToolError.path}',
134+
'--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}',
135+
'--show-warnings',
136+
]),
137+
throwsA(const TypeMatcher<ProcessException>()));
130138
});
131139
});
132140

0 commit comments

Comments
 (0)