如何在 Flutter 小部件测试中停用或忽略布局溢出消息?
How to deactivate or ignore layout overflow messages in Flutter widget tests?
使用 Ahem 字体 测试 运行,字体太大,有时会溢出,破坏测试。有些测试无论如何都不关心溢出,所以应该有办法停用它们。
我有很多测试 运行 在模拟器中正常,但在测试中中断。
我们被迫防止现实中永远不会溢出的小部件溢出,或者为测试提供字体而不是Ahem,只是为了不溢出测试。测试溢出错误是没有意义的,除非你正在做 "overflow error tests".
如何关闭这些错误,或者如何让测试忽略它们?
您不能专门禁用溢出。但还有一些选择:
- 将字体更改为 "real" 字体。您的测试不必使用 Ahem 字体。缺少文档,这是添加此功能的问题:https://github.com/flutter/flutter/issues/17700
- 更改虚拟屏幕大小。参见
- 将
FlutterError.onError
设置为null
根据 @RémiRousselet 的回答,我开发了一个解决方案。
FlutterError.onError = _onError_ignoreOverflowErrors;
Function _onError_ignoreOverflowErrors = (
FlutterErrorDetails details, {
bool forceReport = false,
}) {
assert(details != null);
assert(details.exception != null);
// ---
bool ifIsOverflowError = false;
// Detect overflow error.
var exception = details.exception;
if (exception is FlutterError)
ifIsOverflowError = !exception.diagnostics
.any((e) => e.value.toString().startsWith("A RenderFlex overflowed by"));
// Ignore if is overflow error.
if (ifIsOverflowError)
print('Overflow error.');
// Throw others errors.
else
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
};
这个函数只忽略溢出异常。
如果您的问题纯粹是由 Ahem 字体 有点太大引起的,您可以尝试使用可访问性 textScaleFactor 缩小所有文本,方法是将 WidgetUnderTest 包装在 MediaQuery 中像这样:
MediaQuery(
// Shrink the text avoid overflow caused by large Ahem font.
data: MediaQueryData(textScaleFactor: 0.5),
child: WidgetUnderTest(),
);
这应该比在小部件测试中加载不同的字体要快得多,并且不会因弄乱 FlutterError.onError
而引入丢失错误的风险。但是,如果您的小部件不支持 textScaleFactor,或者溢出是由其他原因引起的,这将无济于事。
请注意,这可能隐藏了一个实际问题。最好的解决方案是修复或重新设计 UI,这样即使使用大字体的 testScaleFactor: 1.5 也不会溢出,因此将字体设置为最大设置的用户将能够使用您的应用程序。
略微改进了 Eduardo 的回答:修复了检测测试,并针对非溢出错误抛出实际异常,以便小部件测试实际上会中断。
Function onError_ignoreOverflowErrors = (
FlutterErrorDetails details, {
bool forceReport = false,
}) {
assert(details != null);
assert(details.exception != null);
var isOverflowError = false;
// Detect overflow error.
var exception = details.exception;
if (exception is FlutterError) {
isOverflowError = exception.diagnostics.any((e) => e.value.toString().contains("A RenderFlex overflowed by"));
}
// Ignore if is overflow error: only report to the console, but do not throw exception as it will
// cause widget tests to fail.
if (isOverflowError) {
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
} else {
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
throw (exception);
}
};
如果文本小部件出现溢出,请使用属性 softWrap: false,像这样
Text(
'text here',
softWrap: false,
)
感谢大佬分享,效果不错!
任何想在测试中使用它的人:
testWidgets('your test name', (tester) async {
disableOverflowErrors();
});
void disableOverflowErrors() {
//TODO MyScreen throws overflow error. Will be investigate in a different ticket.
FlutterError.onError = (FlutterErrorDetails details) {
final exception = details.exception;
final isOverflowError = exception is FlutterError &&
!exception.diagnostics.any(
(e) => e.value.toString().startsWith("A RenderFlex overflowed by"));
if (isOverflowError) {
print(details);
} else {
FlutterError.presentError(details);
}
};
}
使用 Ahem 字体 测试 运行,字体太大,有时会溢出,破坏测试。有些测试无论如何都不关心溢出,所以应该有办法停用它们。
我有很多测试 运行 在模拟器中正常,但在测试中中断。
我们被迫防止现实中永远不会溢出的小部件溢出,或者为测试提供字体而不是Ahem,只是为了不溢出测试。测试溢出错误是没有意义的,除非你正在做 "overflow error tests".
如何关闭这些错误,或者如何让测试忽略它们?
您不能专门禁用溢出。但还有一些选择:
- 将字体更改为 "real" 字体。您的测试不必使用 Ahem 字体。缺少文档,这是添加此功能的问题:https://github.com/flutter/flutter/issues/17700
- 更改虚拟屏幕大小。参见
- 将
FlutterError.onError
设置为null
根据 @RémiRousselet 的回答,我开发了一个解决方案。
FlutterError.onError = _onError_ignoreOverflowErrors;
Function _onError_ignoreOverflowErrors = (
FlutterErrorDetails details, {
bool forceReport = false,
}) {
assert(details != null);
assert(details.exception != null);
// ---
bool ifIsOverflowError = false;
// Detect overflow error.
var exception = details.exception;
if (exception is FlutterError)
ifIsOverflowError = !exception.diagnostics
.any((e) => e.value.toString().startsWith("A RenderFlex overflowed by"));
// Ignore if is overflow error.
if (ifIsOverflowError)
print('Overflow error.');
// Throw others errors.
else
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
};
这个函数只忽略溢出异常。
如果您的问题纯粹是由 Ahem 字体 有点太大引起的,您可以尝试使用可访问性 textScaleFactor 缩小所有文本,方法是将 WidgetUnderTest 包装在 MediaQuery 中像这样:
MediaQuery(
// Shrink the text avoid overflow caused by large Ahem font.
data: MediaQueryData(textScaleFactor: 0.5),
child: WidgetUnderTest(),
);
这应该比在小部件测试中加载不同的字体要快得多,并且不会因弄乱 FlutterError.onError
而引入丢失错误的风险。但是,如果您的小部件不支持 textScaleFactor,或者溢出是由其他原因引起的,这将无济于事。
请注意,这可能隐藏了一个实际问题。最好的解决方案是修复或重新设计 UI,这样即使使用大字体的 testScaleFactor: 1.5 也不会溢出,因此将字体设置为最大设置的用户将能够使用您的应用程序。
略微改进了 Eduardo 的回答:修复了检测测试,并针对非溢出错误抛出实际异常,以便小部件测试实际上会中断。
Function onError_ignoreOverflowErrors = (
FlutterErrorDetails details, {
bool forceReport = false,
}) {
assert(details != null);
assert(details.exception != null);
var isOverflowError = false;
// Detect overflow error.
var exception = details.exception;
if (exception is FlutterError) {
isOverflowError = exception.diagnostics.any((e) => e.value.toString().contains("A RenderFlex overflowed by"));
}
// Ignore if is overflow error: only report to the console, but do not throw exception as it will
// cause widget tests to fail.
if (isOverflowError) {
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
} else {
FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
throw (exception);
}
};
如果文本小部件出现溢出,请使用属性 softWrap: false,像这样
Text(
'text here',
softWrap: false,
)
感谢大佬分享,效果不错!
任何想在测试中使用它的人:
testWidgets('your test name', (tester) async {
disableOverflowErrors();
});
void disableOverflowErrors() {
//TODO MyScreen throws overflow error. Will be investigate in a different ticket.
FlutterError.onError = (FlutterErrorDetails details) {
final exception = details.exception;
final isOverflowError = exception is FlutterError &&
!exception.diagnostics.any(
(e) => e.value.toString().startsWith("A RenderFlex overflowed by"));
if (isOverflowError) {
print(details);
} else {
FlutterError.presentError(details);
}
};
}