This document describes the usage of the TestWrapper
submodule in the test_framework
module of the functional test framework.
The TestWrapper submodule extends the BitcoinTestFramework
functionality to external interactive environments for prototyping and educational purposes. Just like BitcoinTestFramework
, the TestWrapper allows the user to:
- Manage regtest bitcoind subprocesses.
- Access RPC interfaces of these bitcoind instances.
- Log events to functional test logging utility.
The TestWrapper
can be useful in interactive environments such as the Python3 command-line interpreter or Jupyter notebooks running a Python3 kernel, where is is necessary to extend the object lifetime of the underlying BitcoinTestFramework
between user inputs.
- Python3
bitcoind
built in the same bitcoin repository as the TestWrapper.
We can import the TestWrapper by adding the path of the Bitcoin Core test_framework
module to the beginning of the PATH variable, and then importing the TestWrapper
class from the test_wrapper
sub-package.
>>> import sys
>>> sys.path.insert(0, "/path/to/bitcoin/test/functional/test_framework")
>>> from test_framework.test_wrapper import TestWrapper
The following TestWrapper methods manage the lifetime of the underlying bitcoind processes and logging utilities.
TestWrapper.setup()
TestWrapper.shutdown()
The TestWrapper inherits all BitcoinTestFramework members and methods, such as:
TestWrapper.nodes[index].rpc_method()
TestWrapper.log.info("Custom log message")
The following sections demonstrate how to initialize, run and shutdown a TestWrapper object in an interactive Python3 environment.
>>> test = TestWrapper()
>>> test.setup("num_nodes"=2)
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Initializing test directory /path/to/bitcoin_func_test_XXXXXXX
The TestWrapper supports all functional test parameters of the Bitcoin TestFramework class. The full set of argument keywords which can be used to initialize the TestWrapper can be found here.
Note: Running multiple instances of TestWrapper is not allowed.
This also ensures that logging remains consolidated in the same temporary folder. If you need more bitcoind nodes than set by default (1), simply increase the num_nodes
parameter during setup.
>>> test2 = TestWrapper()
>>> test2.setup()
TestWrapper is already running!
Unlike the BitcoinTestFramework class, the TestWrapper keeps the underlying Bitcoind subprocesses (nodes) and logging utilities running, until the user explicitly shuts down the TestWrapper object.
During the time between the setup
and shutdown
calls, all bitcoind
node processes and BitcoinTestFramework convenience methods can be accessed interactively.
Example: Mining a regtest chain
By default, the TestWrapper nodes are initialized with a clean chain. This means that each node has at block height 0 after initialization of the TestWrapper.
>>> test.nodes[0].getblockchaininfo()["blocks"]
0
We now generate 101 regtest blocks, and send these to a wallet address owned by the first node.
>>> address = test.nodes[0].getnewaddress()
>>> test.nodes[0].generatetoaddress(101, address)
['2b98dd0044aae6f1cca7f88a0acf366a4bfe053c7f7b00da3c0d115f03d67efb', ...
Since the two nodes are each initialized to establish a connection to the other during setup
, the second node will receive the newly mined blocks after they propagate.
>>> test.nodes[1].getblockchaininfo()["blocks"]
101
The block rewards of the first block are now spendable by the wallet of the first node.
>>> test.nodes[0].getbalance()
Decimal('50.00000000')
We can also log custom events to the logger.
>>> TestWrapper.log.info("Successfully mined regtest chain!")
Note: Please also consider the functional test readme, which provides an overview of the test-framework. Modules such as key.py, script.py and messages.py are especially useful in constructing objects which can be passed to the bitcoind nodes managed by a running TestWrapper object.
Shutting down the TestWrapper will safely tear down all running bitcoind instances and remove all temporary data and logging directories.
>>> test.shutdown()
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Stopping nodes
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Cleaning up /path/to/bitcoin_func_test_XXXXXXX on exit
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Tests successful
To prevent the logs from being removed after a shutdown, simply set the TestWrapper.options.nocleanup
member to True
.
>>> test.options.nocleanup = True
>>> test.shutdown()
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Stopping nodes
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Not cleaning up dir /path/to/bitcoin_func_test_XXXXXXX on exit
20XX-XX-24TXX:XX:XX.XXXXXXX TestFramework (INFO): Tests successful
The following utility consolidates logs from the bitcoind nodes and the underlying BitcoinTestFramework:
/path/to/bitcoin/test/functional/combine_logs.py '/path/to/bitcoin_func_test_XXXXXXX'