8
$\begingroup$

Seems to me that VerificationTests are a bit verbose:

TestReport[{VerificationTest[StringFreeQ["apple", "lp"], True], 
  VerificationTest[StringFreeQ["apple", "a" ~~ __ ~~ "e"], False], 
  VerificationTest[StringFreeQ["apple", "ap"], False], 
  VerificationTest[StringFreeQ["apple", "x"], True], 
  VerificationTest[StringFreeQ["", "asd"], True]}]

This was the first obvious thing that I tried:

args := {{"apple", "lp"}, {"apple", "a" ~~ __ ~~ "e"}, {"apple", "ap"}, {"apple", "x"}, {"", "asd"}};
results := {True, False, (Pause[2]; False), True, True};

tr = TestReport[
  VerificationTest @@@ Thread[{StringFreeQ @@@ args, results}], 
  TimeConstraint -> Quantity[1, "Seconds"]]

But this solution has many problems:

  • Timing specs and information aren't enforced and preserved
  • Evaluations may leak

What are some elegant ways to cut down the verbosity here without messing with evaluation mechanics of the arguments to VerificationTest?

$\endgroup$
10
$\begingroup$

You can make it look somewhat more pleasant by using simple expression parsers. For example, define an auxiliary head Tests, as follows:

ClearAll[transformTest];
SetAttributes[transformTest, {HoldAll, Listable}];
transformTest[lhs_ -> rhs_] := Hold[VerificationTest[lhs, rhs]];
transformTest[Tests[tests___]] := Thread[transformTest[{tests}], Hold];


ClearAll[Tests];
SetAttributes[Tests, HoldAll];
Tests /: TestReport[t_Tests, args___] :=
  Replace[
    transformTest[t],
    Hold[tests___] :> TestReport[tests, args]
  ];

And now you can use the following syntax:

TestReport @ Tests[
  StringFreeQ["apple", "lp"] -> True, 
  StringFreeQ["apple", "a" ~~ __ ~~ "e"] -> False,
  StringFreeQ["apple", "ap"] -> False, 
  StringFreeQ["apple", "x"] -> True,
  StringFreeQ["", "asd"] -> True
]

which looks a little nicer to me.

$\endgroup$
3
$\begingroup$

You can make your own code work simply enough by controlling evaluating with e.g. Inactive

Inactive[TestReport][
  Inactive[VerificationTest] @@@ 
   Thread[{Inactive[StringFreeQ] @@@ args, results}]] // Activate

or Block:

Block[{StringFreeQ, VerificationTest, TestReport},
  TestReport[VerificationTest @@@ Thread[{StringFreeQ @@@ args, results}]]
]

If writing this myself I would probably use my own heldCases and this:

heldCases[
  Thread @ {args, results},
  {{a_, b_}, r_} :>
    VerificationTest[StringFreeQ[a, b], r]
] /. _[x__] :> TestReport[{x}]

I prefer Leonid's more general approach however.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.