I have 2 pieces of code that are giving me trouble. I test them with Unit-Tests, using cobertura to analyze the test coverage, and I don't understand how the conditional coverage is computed.
This is the first piece:
if ((x.getInt() == a)
|| (x.getInt() == y.getInt()) { ...
Cobertura reports me that 4 cases need to be covered, which seems fine when assumed that short-circuiting is ignored.
Then, in another method I have another (longer) conditional:
if ((x == null)
|| ObjectUtils.equals(x.getInt(), a)
|| ObjectUtils.equals(x.getInt(), y.getInt())) {
...
Here comes the part I don't understand: Cobertura reports that 5/6 cases are covered. I would have expected 8 cases, I could explain 5 cases (considering the x == null), but
how does cobertura handle conditional coverage in these cases, and why does that lead to 6 cases?
Coverage is not measured by testing all possible combinations of boolean flag states, but only those combinations which are sufficient to cover all use cases.
Consider the following class:
public class MyClass {
public boolean allOr(boolean x, boolean y) {
return x || y;
}
public boolean allOr(boolean x, boolean y, boolean z) {
return x || y || z;
}
public boolean allOr(boolean w, boolean x, boolean y, boolean z) {
return w || x || y || z;
}
public boolean allAnd(boolean x, boolean y) {
return x && y;
}
public boolean allAnd(boolean x, boolean y, boolean z) {
return x && y && z;
}
public boolean andOr(boolean x, boolean y, boolean z) {
return x && y || z;
}
public boolean orAnd(boolean x, boolean y, boolean z) {
return (x || y) && z;
}
}
The tests which provide complete coverage are as follows:
public class MyClassTest {
#Test
public void testAllOr2() {
MyClass instance = new MyClass();
// For OR clause, test that all false returns false
assertFalse(instance.allOr(false, false));
// For OR clause, test that any one true returns true
assertTrue(instance.allOr(false, true));
assertTrue(instance.allOr(true, false));
}
#Test
public void testAllOr3() {
MyClass instance = new MyClass();
// For OR clause, test that all false returns false
assertFalse(instance.allOr(false, false, false));
// For OR clause, test that any one true returns true
assertTrue(instance.allOr(false, false, true));
assertTrue(instance.allOr(false, true, false));
assertTrue(instance.allOr(true, false, false));
// These do not add to coverage
// assertTrue(instance.allOr(false, true, true));
// assertTrue(instance.allOr(true, false, true));
// assertTrue(instance.allOr(true, true, false));
// assertTrue(instance.allOr(true, true, true));
}
#Test
public void testAllOr4() {
MyClass instance = new MyClass();
// For OR clause, test that all false returns false
assertFalse(instance.allOr(false, false, false, false));
// For OR clause, test that any one true returns true
assertTrue(instance.allOr(false, false, false, true));
assertTrue(instance.allOr(false, false, true, false));
assertTrue(instance.allOr(false, true, false, false));
assertTrue(instance.allOr(true, false, false, false));
}
#Test
public void testAllAnd2() {
MyClass instance = new MyClass();
// For AND clause, test that all true returns true
assertTrue(instance.allAnd(true, true));
// For AND clause, test that any one false returns false
assertFalse(instance.allAnd(true, false));
assertFalse(instance.allAnd(false, true));
}
#Test
public void testAllAnd3() {
MyClass instance = new MyClass();
// For AND clause, test that all true returns true
assertTrue(instance.allAnd(true, true, true));
// For AND clause, test that any one false returns false
assertFalse(instance.allAnd(false, true, true));
assertFalse(instance.allAnd(true, false, true));
assertFalse(instance.allAnd(true, true, false));
}
#Test
public void testAndOr() {
MyClass instance = new MyClass();
// Since AND takes precedence,
// OR is the external operator, AND is the internal operator
// For the AND clause, false can be achieved in two ways
// Compare to testAllAnd2 # 2, 3
assertFalse(instance.andOr(true, false, false));
assertFalse(instance.andOr(false, true, false));
// This completes the first test case for the external operator
// Compare to testAllOr2 # 1
// Now irrespective of the arguments
// as long as the value returned by the internal operation is false
// we can perform the testAllOr2 # 2
assertTrue(instance.andOr(true, false, true));
// We do not need the case for false, true, true
// because we have tested that no matter what the first two args are
// it does not make a difference as long as one of them is false
// However, if both args are true
// the value returned by the internal operation is true
// we can perform the testAllOr2 # 3
// This is only possible in one way
// Compare testAllAnd2 # 1
assertTrue(instance.andOr(true, true, false));
}
#Test
public void testOrAnd() {
MyClass instance = new MyClass();
// Since OR takes precedence,
// AND is the external operator, OR is the internal operator
// For the OR clause, true can be achieved in two ways
// Compare to testAllOr2 # 2, 3
assertTrue(instance.orAnd(false, true, true));
assertTrue(instance.orAnd(true, false, true));
// This completes the first test case for the external operator
// Compare to testAllAnd2 # 1
// Now irrespective of the arguments
// as long as the value returned by the internal operation is true
// we can perform the testAllAnd2 # 2
assertFalse(instance.orAnd(false, true, false));
// We do not need the case for true, false, false
// because we have tested that no matter what the first two args are
// it does not make a difference as long as one of them is true
// However, if both args are false
// the value returned by the internal operation is false
// we can perform the testAllAnd2 # 3
// This is only possible in one way
// Compare testAllOr2 # 1
assertFalse(instance.orAnd(false, false, true));
}
}
Related
I'm learning Dart, and I'd like to have a method similar to let in Kotlin.
I'd like to use it as:
var variable = ...;// nullable type, for example MyClass?
var test1 = let(variable, (it) => 'non null: ${it.safeAccess()}');
// test1 type is String?
var test2 = let(variable, (it) => 'non null: ${it.safeAccess()}', or: () => 'Default value');
// test2 type is String since either way we return a String
In this example, the variable is a nullable instance of MyClass and the output is a nullable String if no fallback is provided, or a non-null String if a non-null fallback is provided.
Here's the prototype I have written:
typedef O LetCallback<I, O>(I value);
typedef O OrCallback<O>();
O let<I, O>(I? value, LetCallback<I, O> cb, {OrCallback<O>? or}) {
if (value != null) {
return cb(value);
}
if (or != null) {
return or();
}
if (null is O) {
return null;
}
throw Exception("Please provide a default non-null value");
}
Dart complains I can't return null, but I don't understand why it's illegal. I had expected this (in explicit syntax):
var variable = ...;// nullable type, for example MyClass?
var test1 = let<MyClass, String?>(variable, (it) => 'non null: ${it.safeAccess()}');
// I=MyClass, O=String?
var test2 = let<MyClass, String>(variable, (it) => 'non null: ${it.safeAccess()}', or: () => 'Default value');
// I=MyClass, O=String
In my expectation, the compiler would infer the type O as either String? or String, so that return null is legal only if O is nullable.
It seems that using the generic syntax, the types referenced are always non-nullable. Is that so? Is it a limitation of the language? Is it possible to write what I want to achieve, or am I forced to have two implementations? (like let and letNotNull for example)
edit: after writing this, I tried the two implementations route. Here's what I have written:
typedef O LetCallback<I, O>(I value);
typedef O OrCallback<O>();
O letNonNull<I, O>(I? value, LetCallback<I, O> cb, OrCallback<O> or) {
if (value != null) {
return cb(value);
}
return or();
}
O? let<I, O>(I? value, LetCallback<I, O> cb, {OrCallback<O>? or}) {
if (value != null) {
return cb(value);
}
if (or != null) {
return or();
}
}
For some reason, this is legal:
var test = letNonNull(null, (it) => "whatever", () => null)
I had expected that the () => null callback would be a compiler error, since O can't be null (as per my initial observation: I can't return null).
It seems like the null-safety is not fully enforced.
edit2: it seems it's legal only if the type is inferred. E.g.:
letNonNull(null, (it) => "bogus", () => null); // legal
letNonNull<String, String>(null, (it) => "bogus", () => null); // illegal
I had hoped that the inferred types would be non-null...
You can't return null because O can, potentially, be bound to a non-nullable type.
Type variables are not "always non-nullable", but they are always potentially non-nullable. What you return from a function with return type O must be valid for all possible bindings of O, even when it's bound to non-nullable types. Or when it's bound to Never. That means that the only type that can possibly be valid to return is O itself, and null does not have type O.
If you want to always be able to return null, you must make the return type of let be O?. That makes it always nullable, even when O itself is not nullable.
In that case, I'd restrict O to be non-nullable by giving it a bound of extends Object.
The alternative, as you then do, is to return null if null is a valid return value, and throw if it's not (and thereby avoid having to return anything, since you have nothing to return), but your approach doesn't work with the type system.
Try changing
if (null is O) {
return null;
}
to
O? nullReturn = null;
if (nullReturn is O) {
return nullReturn;
}
As stated above, the only type you can return is O, so you want the value null to have type O. You can either do if (null is O) return null as O; (or even just return null as O; and rely on the TypeError from the cast istead of throwing yourself), or you can use type promotion like this example to avoid the extra as.
You probably also want to restrict I to be non-nullable using a bound, and then use I? for the argument to let, but not to cb. That ensures that the inferred I type is always non-nullable.
O let<I extends Object, O>(
I? value,
O Function(I) cb,
{O Function()? or}) {
if (value != null) {
return cb(value);
}
if (or != null) {
return or();
}
O? returnNull = null;
if (returnNull is O) {
return returnNull;
}
throw ArgumentError.value(null, "or",
"Please provide a default non-null value");
}
The letNotNull would also need to put a bound on the type variables:
O letNonNull<I extends Object, O>(
I? value, O Function(I) cb, O Function() or) {
if (value != null) {
return cb(value);
}
return or();
}
The reason
var test = letNonNull(null, (it) => "whatever", () => null)
is valid is that it infers letNotNull<Object, String?>, and
letNonNull<String, String>(null, (it) => "bogus", () => null); // illegal
is invalid because the type for O is not nullable.
The type system doesn't known how that or function argument is going to be used, it just checks that its a proper subtype of the O Function() parameter type for the actual value of O that is supplied.
The type checking of the function body ensures it can only be used in positions where the result is acceptable. That's the type checking which disallowed returning null above because that check has to work for all types that O can be bound to.
I'd consider defining the let operation as an extension method instead, because then it does type inference on the value first, before looking at the callback. Something like:
extension Let<T extends Object> on T? {
R let<R>(R Function(T) callback, {R Function()? or}) {
var self = this;
if (self != null) return callback(self);
if (or != null) return or();
R? nullReturn = null;
if (nullReturn is R) return nullReturn;
throw ArgumentError.notNull("or");
}
}
Just
return null as <The type you want>
This is what I want to implement:
void fun({
bool Function(int i) predicate = (i) => false,
}) {
// do something with 'predicate(something)'
}
But I am getting the error:
The default value of an optional parameter must be constant.dart(non_constant_default_value).
I was able to get arround this error with the following:
bool falsePredicate(int i) => false;
void fun({
bool Function(int i) predicate = falsePredicate,
}) {
// do something with 'predicate(something)'
}
But now the question becomes, why can't I directly create a default function value as in the first set of code? There seems to be no difference between the first and the second cases. How is the function given in the first approach not constant?
As #Noah has pointed to the git discussion, the dart language has this missing piece of compile-time constant functions, which eventually leads to this problem.
Check this post: https://github.com/dart-lang/language/issues/1048
As the post shows, the issue has been raised in mid-2012 and now it's been 8+ years. So the hopes of this being available in the near feature is very less.
However few alternative solutions till then:
Option 1 (separate method):
class ServiceProvider {
static bool falsePredicate(int i) => false;
void fun({
bool Function(int i) predicate = falsePredicate,
}) {
// do something with 'predicate(something)'
}
}
Option 2 (Null checking while using the predicate)
class ServiceProvider {
void fun({
bool Function(int i)? predicate,
}) {
int val = 55; // for demonstration
predicate?.call(val); // Call only if the predicate is non-null
}
}
Option 3 (Only for class constructors)
class ServiceProvider {
final bool Function(int i) _predicate;
ServiceProvider ({bool Function(int i)? predicate})
: _predicate = predicate ?? ((i) => false);
void fun() {
int val = 55;
_predicate(5); // No null check is needed. The predicate is always non-null
}
}
Is it possble to change the whay the logical or || statement is executed in dart.
For example. I have the functions foo() and boo() which have a return type of bool. If i write
(foo() || boo()) ? /* A */ : /* B */;
and foo() returns true boo() would not be executed. I would like to be able to change that, but couldn't find a way to do so.
I was surprised to see that this will not help:
bool helper = false;
helper = helper || foo();
helper = helper || boo();
(helper) ? /* A */ : /* B */
boo() is only executed when foo() returns true, because the result would be false anyway (short-circuit). You have to force explicit execution like:
var f = foo();
var b = boo();
(f || b) ? print('false') : print('true');
If you want to use it inline you can use a custom method like mentioned by #AlexandreArdhuin or
[foo(), boo()].reduce((v1, v2) => v1 || v2)
? print('false') : print('true');
Try it in DartPad.
You can not use | in dart but you can write an helper function like or and have a syntax quite close:
main() {
if (or([foo(), boo()])) {
print('ok');
}
}
bool or(List<bool> values) => values.fold(false, (t, e) => t || e);
bool foo() {
print("foo");
return true;
}
bool boo() {
print("boo");
return true;
}
Try it in DartPad.
non-short-circuit boolean operators is the phrase you are looking for, and it is not possible at the moment, see https://github.com/dart-lang/sdk/issues/1080
On Dart 1.0.0, I just tried:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b = true]) {
if(?b) {
// ...
}
}
}
And am getting a compiler error on the ?b part:
The argument definition test ('?' operator) has been deprecated
So what's the "new" way of testing for whether or not an argument was supplied?
There is no way to test if an argument was provided or not. The main-reason for its removal was, that it was very complex to forward calls this way.
The generally preferred way is to use null as "not given". This doesn't always work (for example if null is a valid value), and won't catch bad arguments. If null is used, then the parameter must not have a default-value. Otherwise the parameter is not null but takes the default-value:
foo([x = true, y]) => print("$x, $y");
foo(); // prints "true, null"
So in your case you should probably do:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if(b == null) { // treat as if not given.
// ...
}
}
}
This makes new MyClass(5, null) and new MyClass(5) identical. If you really need to catch the first case, you have to work around the type-system:
class _Sentinel { const _Sentinel(); }
...
MyClass(int x, [b = const _Sentinel()]) {
if (b == const _Sentinel()) b = true;
...
}
This way you can check if an argument has been provided. In return you lose the type on b.
The argument definition test operator was deprecated because it was redundant with checking for null; an optional parameter that was omitted would get the value null, and the caller could've passed null explicitly anyway. So instead use == null:
class MyClass {
int x;
bool b;
MyClass(int x, [bool b]) {
if (b == null) {
// throw exception or assign default value for b
}
}
}
I have a problem in registering custom property editor. I register it like this:
class BooleanEditorRegistrar implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Boolean.class,
new CustomBooleanEditor(CustomBooleanEditor.VALUE_YES, CustomBooleanEditor.VALUE_NO, false))
registry.registerCustomEditor(Boolean.class,
new CustomBooleanEditor(CustomBooleanEditor.VALUE_ON, CustomBooleanEditor.VALUE_OFF, true))
}
}
But the only first is applied. Is it possible to register more then one?
You can only set one property editor per class. If you are using Spring's CustomBooleanEditor, you can either use the default values ("true"/"on"/"yes"/"1", "false"/"off"/"no"/"0") with the one-arg constructor, or exactly one string each for true and false. If you need something more flexible, you'll have to implement your own property editor. For example:
import org.springframework.beans.propertyeditors.CustomBooleanEditor
class MyBooleanEditor extends CustomBooleanEditor {
def strings = [
(VALUE_YES): true,
(VALUE_ON): true,
(VALUE_NO): false,
(VALUE_OFF): false
]
MyBooleanEditor() {
super(false)
}
void setAsText(String text) {
def val = strings[text.toLowerCase()]
if (val != null) {
setValue(val)
} else {
throw new IllegalArgumentException("Invalid boolean value [" + text + "]")
}
}
}