Skip to content
On this page

Test scenario

The test scenario is essential for testing. It lets you work with contracts, calculate expressions, set flags, and more. Essentially, it mimics the Tezos blockchain for testing to ensure contracts work correctly before deployment.


The test scenario must be defined before any instantiation as the instance is using the scenario to pre-compile the contract.

sp.test_scenario(name: str, modules: list[sp.module] | sp.module) → test_scenario

Returns a test scenario.

There must be at most one test scenario per test function and it should be defined as the first instruction.

def test():
    # Create a test scenario
    sc = sp.test_scenario("A Test", main)


sp.is_failing(expression) → 

Returns True when an expression (views, lambdas, ...) results in failure, and False when the expression succeeds.

Content of exceptions

sp.catch_exception(expression, [t]) → sp.option[t]

t is optional, just using sp.catch_exception(<expression>) will be valid in most situations.

This method is used to test failing conditions of expressions (views, lambdas, ...). It returns an sp.option of type t that will contain sp.Some(<exception>) when the expression fails or None if it succeeds.


Views, both off-chain or on-chain, can now be called from test scenarios the same way as entrypoints. The example below shows how to do it.


import smartpy as sp

def main():
  class MyContract(sp.Contract):
      def __init__(self, param):
 = param

      def myEntrypoint(self, n): = n

      def state(self, param):
          assert param < 5, "This is false: param > 5"
          return * param

def test():
    scenario = sp.test_scenario("Minimal", main)
    c1 = main.MyContract(1)
    scenario += c1

    """ Test views """

    # Display the offchain call result

    # Assert the view result
    scenario.verify(c1.state(2) == 2)
    # Assert call failures
    scenario.verify(sp.is_failing(c1.state(6)));    # Expected to fail
    scenario.verify(~ sp.is_failing(c1.state(1)));   # Not expected to fail

    # Assert exception result
    # catch_exception returns an option:
    #      None if the call succeeds
    #      sp.Some(<exception>) if the call fails
    e = sp.catch_exception(c1.state(7), t = sp.string)
    scenario.verify(e == sp.Some("This is false: param > 5"))

Document extra information

sc.h<N>(content: str) → 

Add a section heading of the level <N>.

<h1> is the highest section level.

scenario.h1("a title")
scenario.h2("a subtitle")
scenario.h3('Equivalent to <h3> HTML tag.')
scenario.h4("Equivalent to <h4> HTML tag.")
sc.p(content: str) → 

Add a text paragraph to the scenario equivalent to <p>.

scenario.p("Equivalent to <p> HTML tag.")


Showing expressions, html = True) → 

To show expressions, we use, html = True).

htmlboolTrue by default, False to export not in html but like in source code.
python, html = True) * 12)

Computing expressions

sc.compute(expression, **context_args) → t

To compute expressions, we use scenario.compute(<expression>, **context_args).

x = scenario.compute( * 12)

The variable x can now be used in the sequel of the scenario and its value is fixed.

Compute optional arguments

Generic context arguments are:

sendersp.address or sp.test_accountsp.senderThe simulated sender of the computation.
Specific to computation.
sourcesp.address or sp.test_accountsp.sourceThe simulated source of the computation.
Specific to computation.
chain_idsp.chain_idsp.chain_idThe simulated chain_id.
Preserved until changed.
levelsp.natsp.levelThe simulated block level.
Preserved until changed.
nowsp.timestampsp.nowThe simulated block timestamp.
Preserved until changed.[sp.key_hash, sp.nat]sp.total_voting_power,
The simulated voting powers for the test.
Preserved until changed.


sc.verify(expression) → 

To verify conditions, we use scenario.verify(<condition>).

scenario.verify( == 51)
sc.verify_equal(expr1, expr2) → 

To verify an equality condition, we can also use scenario.verify_equal(<left_expression>, <right_expression>) which works on both comparable and non-comparable types.

scenario.verify_equal(, [2, 3, 5, 7])

Dynamic contracts

Contracts in SmartPy can be created in two ways, statically as shown above, or
dynamically via a call to the sp.create_contract statement from within an entrypoint.

We can refer to a contract that was created dynamically using scenario.dynamic_contract(<module>.<Contract>, offset), this returns a handle that can then be used as for static contracts.

sc.dynamic_contract(template_ref: sp.Contract, offset:int | None) → sp.contract[t]

Returns a handle to the dynamic contract of class type template_ref=<module>.<Contract> that was created at offset.

The template_ref is used to check that the referenced contract has the correct class type.

The offset, if given, specifies the position in the list of dynamic contracts created so far. So offset=0 would refer to the first dynamically created contract and offset=-1 would refer to the most recently created dynamic contract. If not given it will default to the most recently created dynamic contract.

For example, to refer to the most recently created dynamic contract and check the class type is main.MyContract, we would use

dyn = scenario.dynamic_contract(main.MyContract)


dyn = scenario.dynamic_contract(main.MyContract, offset=-2)

will refer to the last but one dynamic contract and check the class type is main.MyContract.

The handle dyn can now be used to call entrypoints, verify data etc

scenario.verify( == 3)