Commit e08c3c3b authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

moreOrLessEquals matcher for floating point numbers (#7358)

```dart
expect(x, moreOrLessEquals(0.0));
```

...for those cases where `x` might be 1e-11 or whatever.

Also, be more resilient when dumping the tree from inside the test framework.
Also, add an assert that helped me debug something the other day.
parent 7f3dc76b
...@@ -49,6 +49,7 @@ class _DepthFirstChildIterator implements Iterator<Element> { ...@@ -49,6 +49,7 @@ class _DepthFirstChildIterator implements Iterator<Element> {
} }
static Iterable<Element> _reverseChildrenOf(Element element, bool skipOffstage) { static Iterable<Element> _reverseChildrenOf(Element element, bool skipOffstage) {
assert(element != null);
final List<Element> children = <Element>[]; final List<Element> children = <Element>[];
if (skipOffstage) { if (skipOffstage) {
element.visitChildrenForSemantics(children.add); element.visitChildrenForSemantics(children.add);
......
...@@ -334,7 +334,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase ...@@ -334,7 +334,12 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
// _this_ zone, the test framework would find this zone was the current // _this_ zone, the test framework would find this zone was the current
// zone and helpfully throw the error in this zone, causing us to be // zone and helpfully throw the error in this zone, causing us to be
// directly called again. // directly called again.
final String treeDump = renderViewElement?.toStringDeep() ?? '<no tree>'; String treeDump;
try {
treeDump = renderViewElement?.toStringDeep() ?? '<no tree>';
} catch (exception) {
treeDump = '<additional error caught while dumping tree: $exception>';
}
final StringBuffer expectLine = new StringBuffer(); final StringBuffer expectLine = new StringBuffer();
final int stackLinesToOmit = reportExpectCall(stack, expectLine); final int stackLinesToOmit = reportExpectCall(stack, expectLine);
FlutterError.reportError(new FlutterErrorDetails( FlutterError.reportError(new FlutterErrorDetails(
......
...@@ -66,6 +66,17 @@ const Matcher isNotInCard = const _IsNotInCard(); ...@@ -66,6 +66,17 @@ const Matcher isNotInCard = const _IsNotInCard();
/// empty. /// empty.
const Matcher hasOneLineDescription = const _HasOneLineDescription(); const Matcher hasOneLineDescription = const _HasOneLineDescription();
/// Asserts that two [double]s are equal, within some tolerated error.
///
/// Two values are considered equal if the difference between them is within
/// 1e-10 of the larger one. This is an arbitrary value which can be adjusted
/// using the `epsilon` argument. This matcher is intended to compare floating
/// point numbers that are the result of different sequences of operations, such
/// that they may have accumulated slightly different errors.
Matcher moreOrLessEquals(double value, { double epsilon: 1e-10 }) {
return new _MoreOrLessEquals(value, epsilon);
}
class _FindsWidgetMatcher extends Matcher { class _FindsWidgetMatcher extends Matcher {
const _FindsWidgetMatcher(this.min, this.max); const _FindsWidgetMatcher(this.min, this.max);
...@@ -237,3 +248,23 @@ class _HasOneLineDescription extends Matcher { ...@@ -237,3 +248,23 @@ class _HasOneLineDescription extends Matcher {
@override @override
Description describe(Description description) => description.add('one line description'); Description describe(Description description) => description.add('one line description');
} }
class _MoreOrLessEquals extends Matcher {
const _MoreOrLessEquals(this.value, this.epsilon);
final double value;
final double epsilon;
@override
bool matches(Object object, Map<dynamic, dynamic> matchState) {
if (object is! double)
return false;
if (object == value)
return true;
final double test = object;
return (test - value).abs() <= epsilon;
}
@override
Description describe(Description description) => description.add('$value$epsilon)');
}
\ No newline at end of file
// Copyright 2016 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 'package:flutter_test/flutter_test.dart';
void main() {
test('moreOrLessEquals', () {
expect(0.0, moreOrLessEquals(1e-11));
expect(1e-11, moreOrLessEquals(0.0));
expect(-1e-11, moreOrLessEquals(0.0));
expect(0.0, isNot(moreOrLessEquals(1e11)));
expect(1e11, isNot(moreOrLessEquals(0.0)));
expect(-1e11, isNot(moreOrLessEquals(0.0)));
expect(0.0, isNot(moreOrLessEquals(1.0)));
expect(1.0, isNot(moreOrLessEquals(0.0)));
expect(-1.0, isNot(moreOrLessEquals(0.0)));
expect(1e-11, moreOrLessEquals(-1e-11));
expect(-1e-11, moreOrLessEquals(1e-11));
expect(11.0, isNot(moreOrLessEquals(-11.0, epsilon: 1.0)));
expect(-11.0, isNot(moreOrLessEquals(11.0, epsilon: 1.0)));
expect(11.0, moreOrLessEquals(-11.0, epsilon: 100.0));
expect(-11.0, moreOrLessEquals(11.0, epsilon: 100.0));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment