user1007: Is there infrastructure for writing unit/integration tests for our contracts, without running the full playground?  Is there a test-focused EvaluatorTrace monad, for example?

user2042: There are now test capabilities in the Plutus.Contract.Test module which uses the Tasty library.
This is explained more fully in the unit tests section of lecture 8 of iteration 1 of the Plutus Pioneer Program.
Some highlights:
checkPredicate :: String -> TracePredicate -> EmulatorTrace () -> TestTree

There are a number of functions for producing a TracePredicate. For example:
-- | Check that the funds in the wallet have changed by the given amount, exluding fees.
walletFundsChange :: Wallet -> Value -> TracePredicate

Which can then be combined into a test function:
tests :: TestTree
tests = checkPredicateOptions
   (defaultCheckOptions & emulatorConfig .~ emCfg)
"token sale trace"
   ( walletFundsChange (Wallet 1) (Ada.lovelaceValueOf   10_000_000  <> assetClassValue token (-60))
.&&. walletFundsChange (Wallet 2) (Ada.lovelaceValueOf (-20_000_000) <> assetClassValue token   20)
.&&. walletFundsChange (Wallet 3) (Ada.lovelaceValueOf (- 5_000_000) <> assetClassValue token    5)
   )
myTrace

Which can then be run like this:
Prelude Spec.Trace> import Test.Tasty
Prelude Test.Tasty Spec.Trace> defaultMain tests
token sale trace: OK (1.22s)

All 1 tests passed (1.22s)

Naturally, these tests can be configured to run as part of "cabal test".

1007: <p>Is there infrastructure for writing unit/integration tests for our contracts, without running the full playground?  Is there a test-focused EvaluatorTrace monad, for example?</p>
 2042: <p>There are now test capabilities in the Plutus.Contract.Test module which uses the Tasty library.</p>
<p>This is explained more fully in <a href="https://plutus-pioneer-program.readthedocs.io/en/latest/week8.html#unit-testing" rel="nofollow noreferrer">the unit tests section of lecture 8 of iteration 1 of the Plutus Pioneer Program</a>.</p>
<p>Some highlights:</p>
<pre><code>checkPredicate :: String -&gt; TracePredicate -&gt; EmulatorTrace () -&gt; TestTree
</code></pre>
<p>There are a number of functions for producing a TracePredicate. For example:</p>
<pre><code>-- | Check that the funds in the wallet have changed by the given amount, exluding fees.
walletFundsChange :: Wallet -&gt; Value -&gt; TracePredicate
</code></pre>
<p>Which can then be combined into a test function:</p>
<pre><code>tests :: TestTree
tests = checkPredicateOptions
   (defaultCheckOptions &amp; emulatorConfig .~ emCfg)
&quot;token sale trace&quot;
   ( walletFundsChange (Wallet 1) (Ada.lovelaceValueOf   10_000_000  &lt;&gt; assetClassValue token (-60))
.&amp;&amp;. walletFundsChange (Wallet 2) (Ada.lovelaceValueOf (-20_000_000) &lt;&gt; assetClassValue token   20)
.&amp;&amp;. walletFundsChange (Wallet 3) (Ada.lovelaceValueOf (- 5_000_000) &lt;&gt; assetClassValue token    5)
   )
myTrace
</code></pre>
<p>Which can then be run like this:</p>
<pre><code>Prelude Spec.Trace&gt; import Test.Tasty
Prelude Test.Tasty Spec.Trace&gt; defaultMain tests
token sale trace: OK (1.22s)

All 1 tests passed (1.22s)
</code></pre>
<p>Naturally, these tests can be configured to run as part of &quot;cabal test&quot;.</p>
