From 28dfb448649c20c032f027c92942ada36f6e4283 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 2 Nov 2017 16:42:28 -0700 Subject: [PATCH] Use Stdout.terminalColumns for line length (#716) Use Stdout.terminalColumns for line length Fall back on a 200-character default, which is less likely to obscure test names when printing to a non-terminal destination. Closes #86 --- CHANGELOG.md | 5 ++ lib/src/runner/reporter/compact.dart | 16 +++---- lib/src/runner/reporter/expanded.dart | 12 ++--- lib/src/util/io.dart | 47 +++++++++++++++++++ lib/src/utils.dart | 34 -------------- pubspec.yaml | 2 +- test/runner/compact_reporter_test.dart | 20 ++++---- test/runner/configuration/top_level_test.dart | 6 +-- test/runner/pause_after_load_test.dart | 32 ++++++------- 9 files changed, 93 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3c59dd10f724..e38fd1f378769 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.12.27 + +* When running in an interactive terminal, the test runner now prints status + lines as wide as the terminal and no wider. + ## 0.12.26+1 * Fix lower bound on package `stack_trace`. Now 1.6.0. diff --git a/lib/src/runner/reporter/compact.dart b/lib/src/runner/reporter/compact.dart index cb4cc9acbb2d2..2a189962326cf 100644 --- a/lib/src/runner/reporter/compact.dart +++ b/lib/src/runner/reporter/compact.dart @@ -11,17 +11,13 @@ import '../../backend/message.dart'; import '../../backend/state.dart'; import '../../utils.dart'; import '../../utils.dart' as utils; +import '../../util/io.dart'; import '../configuration.dart'; import '../engine.dart'; import '../load_exception.dart'; import '../load_suite.dart'; import '../reporter.dart'; -/// The maximum console line length. -/// -/// Lines longer than this will be cropped. -const _lineLength = 100; - /// A reporter that prints test results to the console in a single /// continuously-updating line. class CompactReporter implements Reporter { @@ -251,7 +247,7 @@ class CompactReporter implements Reporter { stdout.write(message); // Add extra padding to overwrite any load messages. - if (!_printedNewline) stdout.write(" " * (_lineLength - message.length)); + if (!_printedNewline) stdout.write(" " * (lineLength - message.length)); stdout.writeln(); } else if (!success) { _progressLine('Some tests failed.', color: _red); @@ -268,7 +264,7 @@ class CompactReporter implements Reporter { /// Prints a line representing the current state of the tests. /// /// [message] goes after the progress report, and may be truncated to fit the - /// entire line within [_lineLength]. If [color] is passed, it's used as the + /// entire line within [lineLength]. If [color] is passed, it's used as the /// color for [message]. If [suffix] is passed, it's added to the end of /// [message]. bool _progressLine(String message, @@ -329,16 +325,16 @@ class CompactReporter implements Reporter { buffer.write(': '); buffer.write(color); - // Ensure the line fits within [_lineLength]. [buffer] includes the color + // Ensure the line fits within [lineLength]. [buffer] includes the color // escape sequences too. Because these sequences are not visible characters, // we make sure they are not counted towards the limit. var length = withoutColors(buffer.toString()).length; - if (truncate) message = utils.truncate(message, _lineLength - length); + if (truncate) message = utils.truncate(message, lineLength - length); buffer.write(message); buffer.write(_noColor); // Pad the rest of the line so that it looks erased. - buffer.write(' ' * (_lineLength - withoutColors(buffer.toString()).length)); + buffer.write(' ' * (lineLength - withoutColors(buffer.toString()).length)); stdout.write(buffer.toString()); _printedNewline = false; diff --git a/lib/src/runner/reporter/expanded.dart b/lib/src/runner/reporter/expanded.dart index 00d7915be1880..eb0b99adb49b3 100644 --- a/lib/src/runner/reporter/expanded.dart +++ b/lib/src/runner/reporter/expanded.dart @@ -14,11 +14,6 @@ import '../load_exception.dart'; import '../load_suite.dart'; import '../reporter.dart'; -/// The maximum console line length. -/// -/// Lines longer than this will be cropped. -const _lineLength = 100; - /// A reporter that prints each test on its own line. /// /// This is currently used in place of [CompactReporter] by `lib/test.dart`, @@ -238,10 +233,9 @@ class ExpandedReporter implements Reporter { /// Prints a line representing the current state of the tests. /// - /// [message] goes after the progress report, and may be truncated to fit the - /// entire line within [_lineLength]. If [color] is passed, it's used as the - /// color for [message]. If [suffix] is passed, it's added to the end of - /// [message]. + /// [message] goes after the progress report. If [color] is passed, it's used + /// as the color for [message]. If [suffix] is passed, it's added to the end + /// of [message]. void _progressLine(String message, {String color, String suffix}) { // Print nothing if nothing has changed since the last progress line. if (_engine.passed.length == _lastProgressPassed && diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart index 91a90fdb81268..90fd561de1583 100644 --- a/lib/src/util/io.dart +++ b/lib/src/util/io.dart @@ -18,6 +18,23 @@ const _newline = 0xA; /// The ASCII code for a carriage return character. const _carriageReturn = 0xD; +/// The default line length for output when there isn't a terminal attached to +/// stdout. +const _defaultLineLength = 200; + +/// The maximum line length for output. +final int lineLength = () { + try { + return stdout.terminalColumns; + } on UnsupportedError { + // This can throw an [UnsupportedError] if we're running in a JS context + // where `dart:io` is unavaiable. + return _defaultLineLength; + } on StdoutException { + return _defaultLineLength; + } +}(); + /// The root directory of the Dart SDK. final String sdkDir = p.dirname(p.dirname(Platform.resolvedExecutable)); @@ -103,6 +120,36 @@ Stream> sanitizeForWindows(Stream> input) { }); } +/// Wraps [text] so that it fits within [lineLength]. +/// +/// This preserves existing newlines and doesn't consider terminal color escapes +/// part of a word's length. It only splits words on spaces, not on other sorts +/// of whitespace. +String wordWrap(String text) { + return text.split("\n").map((originalLine) { + var buffer = new StringBuffer(); + var lengthSoFar = 0; + for (var word in originalLine.split(" ")) { + var wordLength = withoutColors(word).length; + if (wordLength > lineLength) { + if (lengthSoFar != 0) buffer.writeln(); + buffer.writeln(word); + } else if (lengthSoFar == 0) { + buffer.write(word); + lengthSoFar = wordLength; + } else if (lengthSoFar + 1 + wordLength > lineLength) { + buffer.writeln(); + buffer.write(word); + lengthSoFar = wordLength; + } else { + buffer.write(" $word"); + lengthSoFar += 1 + wordLength; + } + } + return buffer.toString(); + }).join("\n"); +} + /// Print a warning containing [message]. /// /// This automatically wraps lines if they get too long. If [color] is passed, diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 2e06ef1c1a633..c84a0c13d383b 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -17,9 +17,6 @@ import 'package:term_glyph/term_glyph.dart' as glyph; import 'backend/invoker.dart'; import 'backend/operating_system.dart'; -/// The maximum console line length. -const _lineLength = 100; - /// A typedef for a possibly-asynchronous function. /// /// The return type should only ever by [Future] or void. @@ -140,37 +137,6 @@ String pluralize(String name, int number, {String plural}) { /// whether its first letter is a vowel. String a(String noun) => noun.startsWith(_vowel) ? "an $noun" : "a $noun"; -/// Wraps [text] so that it fits within [lineLength], which defaults to 100 -/// characters. -/// -/// This preserves existing newlines and doesn't consider terminal color escapes -/// part of a word's length. -String wordWrap(String text, {int lineLength}) { - if (lineLength == null) lineLength = _lineLength; - return text.split("\n").map((originalLine) { - var buffer = new StringBuffer(); - var lengthSoFar = 0; - for (var word in originalLine.split(" ")) { - var wordLength = withoutColors(word).length; - if (wordLength > lineLength) { - if (lengthSoFar != 0) buffer.writeln(); - buffer.writeln(word); - } else if (lengthSoFar == 0) { - buffer.write(word); - lengthSoFar = wordLength; - } else if (lengthSoFar + 1 + wordLength > lineLength) { - buffer.writeln(); - buffer.write(word); - lengthSoFar = wordLength; - } else { - buffer.write(" $word"); - lengthSoFar += 1 + wordLength; - } - } - return buffer.toString(); - }).join("\n"); -} - /// A regular expression matching terminal color codes. final _colorCode = new RegExp('\u001b\\[[0-9;]+m'); diff --git a/pubspec.yaml b/pubspec.yaml index 8cdb1fc52a958..5c20d16eb8e47 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: test -version: 0.12.26+1 +version: 0.12.27-dev author: Dart Team description: A library for writing dart unit tests. homepage: https://github.com/dart-lang/test diff --git a/test/runner/compact_reporter_test.dart b/test/runner/compact_reporter_test.dart index ca9cc8aab24f7..39a92f7a5ff72 100644 --- a/test/runner/compact_reporter_test.dart +++ b/test/runner/compact_reporter_test.dart @@ -149,13 +149,15 @@ void main() { return _expectReport(""" test( 'really gosh dang long test name. Even longer than that. No, yet ' - 'longer. A little more... okay, that should do it.', + 'longer. Even more. We have to get to at least 200 characters. ' + 'I know that seems like a lot, but I believe in you. A little ' + 'more... okay, that should do it.', () => throw new TestFailure('oh no'));""", """ +0: loading test.dart - +0: really ... longer than that. No, yet longer. A little more... okay, that should do it. - +0 -1: really gosh dang long test name. Even longer than that. No, yet longer. A little more... okay, that should do it. [E] + +0: really ... than that. No, yet longer. Even more. We have to get to at least 200 characters. I know that seems like a lot, but I believe in you. A little more... okay, that should do it. + +0 -1: really gosh dang long test name. Even longer than that. No, yet longer. Even more. We have to get to at least 200 characters. I know that seems like a lot, but I believe in you. A little more... okay, that should do it. [E] oh no - test.dart 9:18 main. + test.dart 11:18 main. +0 -1: Some tests failed."""); @@ -268,14 +270,16 @@ void main() { return _expectReport(""" test( 'really gosh dang long test name. Even longer than that. No, yet ' - 'longer. A little more... okay, that should do it.', + 'longer. Even more. We have to get to at least 200 ' + 'characters. I know that seems like a lot, but I believe in ' + 'you. A little more... okay, that should do it.', () => print('hello'));""", """ +0: loading test.dart - +0: really ... longer than that. No, yet longer. A little more... okay, that should do it. - +0: really gosh dang long test name. Even longer than that. No, yet longer. A little more... okay, that should do it. + +0: really ... than that. No, yet longer. Even more. We have to get to at least 200 characters. I know that seems like a lot, but I believe in you. A little more... okay, that should do it. + +0: really gosh dang long test name. Even longer than that. No, yet longer. Even more. We have to get to at least 200 characters. I know that seems like a lot, but I believe in you. A little more... okay, that should do it. hello - +1: really ... longer than that. No, yet longer. A little more... okay, that should do it. + +1: really ... than that. No, yet longer. Even more. We have to get to at least 200 characters. I know that seems like a lot, but I believe in you. A little more... okay, that should do it. +1: All tests passed!"""); }); diff --git a/test/runner/configuration/top_level_test.dart b/test/runner/configuration/top_level_test.dart index 75fe33372b4d2..644f8fdf0bb96 100644 --- a/test/runner/configuration/top_level_test.dart +++ b/test/runner/configuration/top_level_test.dart @@ -76,9 +76,9 @@ void main() { "", startsWith("Observatory URL: "), startsWith("Remote debugger URL: "), - "The test runner is paused. Open the remote debugger or the Observatory " - "and set breakpoints. Once", - "you're finished, return to this terminal and press Enter." + "The test runner is paused. Open the remote debugger or the " + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ])); var nextLineFired = false; diff --git a/test/runner/pause_after_load_test.dart b/test/runner/pause_after_load_test.dart index 7696eb8b2a477..ac93de2576ff0 100644 --- a/test/runner/pause_after_load_test.dart +++ b/test/runner/pause_after_load_test.dart @@ -44,8 +44,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); var nextLineFired = false; @@ -67,8 +67,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); nextLineFired = false; @@ -108,8 +108,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); var nextLineFired = false; @@ -130,8 +130,8 @@ void main() { test.stdout, emitsThrough(emitsInOrder([ "The test runner is paused. Open the dev console in Chrome and set " - "breakpoints. Once you're finished,", - "return to this terminal and press Enter." + "breakpoints. Once you're finished, return to this terminal and " + "press Enter." ]))); nextLineFired = false; @@ -191,8 +191,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); var nextLineFired = false; @@ -234,8 +234,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); test.signal(ProcessSignal.SIGTERM); @@ -266,8 +266,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); var nextLineFired = false; @@ -309,8 +309,8 @@ void main() { emitsThrough(emitsInOrder([ startsWith("Observatory URL: "), "The test runner is paused. Open the dev console in Dartium or the " - "Observatory and set breakpoints.", - "Once you're finished, return to this terminal and press Enter." + "Observatory and set breakpoints. Once you're finished, return " + "to this terminal and press Enter." ]))); var nextLineFired = false;