1Test Shell for Interactive Environments 2========================================= 3 4This document describes how to use the `TestShell` submodule in the functional 5test suite. 6 7The `TestShell` submodule extends the `BitcoinTestFramework` functionality to 8external interactive environments for prototyping and educational purposes. Just 9like `BitcoinTestFramework`, the `TestShell` allows the user to: 10 11* Manage regtest bitcoind subprocesses. 12* Access RPC interfaces of the underlying bitcoind instances. 13* Log events to the functional test logging utility. 14 15The `TestShell` can be useful in interactive environments where it is necessary 16to extend the object lifetime of the underlying `BitcoinTestFramework` between 17user inputs. Such environments include the Python3 command line interpreter or 18[Jupyter](https://jupyter.org/) notebooks running a Python3 kernel. 19 20## 1. Requirements 21 22* Python3 23* `bitcoind` built in the same repository as the `TestShell`. 24 25## 2. Importing `TestShell` from the Bitcoin Core repository 26 27We can import the `TestShell` by adding the path of the Bitcoin Core 28`test_framework` module to the beginning of the PATH variable, and then 29importing the `TestShell` class from the `test_shell` sub-package. 30 31``` 32>>> import sys 33>>> sys.path.insert(0, "/path/to/bitcoin/test/functional") 34>>> from test_framework.test_shell import TestShell 35``` 36 37The following `TestShell` methods manage the lifetime of the underlying bitcoind 38processes and logging utilities. 39 40* `TestShell.setup()` 41* `TestShell.shutdown()` 42 43The `TestShell` inherits all `BitcoinTestFramework` members and methods, such 44as: 45* `TestShell.nodes[index].rpc_method()` 46* `TestShell.log.info("Custom log message")` 47 48The following sections demonstrate how to initialize, run, and shut down a 49`TestShell` object. 50 51## 3. Initializing a `TestShell` object 52 53``` 54>>> test = TestShell().setup(num_nodes=2, setup_clean_chain=True) 5520XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Initializing test directory /path/to/bitcoin_func_test_XXXXXXX 56``` 57The `TestShell` forwards all functional test parameters of the parent 58`BitcoinTestFramework` object. The full set of argument keywords which can be 59used to initialize the `TestShell` can be found in [section 60#6](#custom-testshell-parameters) of this document. 61 62**Note: Running multiple instances of `TestShell` is not allowed.** Running a 63single process also ensures that logging remains consolidated in the same 64temporary folder. If you need more bitcoind nodes than set by default (1), 65simply increase the `num_nodes` parameter during setup. 66 67``` 68>>> test2 = TestShell().setup() 69TestShell is already running! 70``` 71 72## 4. Interacting with the `TestShell` 73 74Unlike the `BitcoinTestFramework` class, the `TestShell` keeps the underlying 75Bitcoind subprocesses (nodes) and logging utilities running until the user 76explicitly shuts down the `TestShell` object. 77 78During the time between the `setup` and `shutdown` calls, all `bitcoind` node 79processes and `BitcoinTestFramework` convenience methods can be accessed 80interactively. 81 82**Example: Mining a regtest chain** 83 84By default, the `TestShell` nodes are initialized with a clean chain. This means 85that each node of the `TestShell` is initialized with a block height of 0. 86 87``` 88>>> test.nodes[0].getblockchaininfo()["blocks"] 890 90``` 91 92We now let the first node generate 101 regtest blocks, and direct the coinbase 93rewards to a wallet address owned by the mining node. 94 95``` 96>>> address = test.nodes[0].getnewaddress() 97>>> test.nodes[0].generatetoaddress(101, address) 98['2b98dd0044aae6f1cca7f88a0acf366a4bfe053c7f7b00da3c0d115f03d67efb', ... 99``` 100Since the two nodes are both initialized by default to establish an outbound 101connection to each other during `setup`, the second node's chain will include 102the mined blocks as soon as they propagate. 103 104``` 105>>> test.nodes[1].getblockchaininfo()["blocks"] 106101 107``` 108The block rewards from the first block are now spendable by the wallet of the 109first node. 110 111``` 112>>> test.nodes[0].getbalance() 113Decimal('50.00000000') 114``` 115 116We can also log custom events to the logger. 117 118``` 119>>> test.nodes[0].log.info("Successfully mined regtest chain!") 12020XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework.node0 (INFO): Successfully mined regtest chain! 121``` 122 123**Note: Please also consider the functional test 124[readme](../test/functional/README.md), which provides an overview of the 125test-framework**. Modules such as 126[key.py](../test/functional/test_framework/key.py), 127[script.py](../test/functional/test_framework/script.py) and 128[messages.py](../test/functional/test_framework/messages.py) are particularly 129useful in constructing objects which can be passed to the bitcoind nodes managed 130by a running `TestShell` object. 131 132## 5. Shutting the `TestShell` down 133 134Shutting down the `TestShell` will safely tear down all running bitcoind 135instances and remove all temporary data and logging directories. 136 137``` 138>>> test.shutdown() 13920XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Stopping nodes 14020XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Cleaning up /path/to/bitcoin_func_test_XXXXXXX on exit 14120XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Tests successful 142``` 143To prevent the logs from being removed after a shutdown, simply set the 144`TestShell.options.nocleanup` member to `True`. 145``` 146>>> test.options.nocleanup = True 147>>> test.shutdown() 14820XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Stopping nodes 14920XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Not cleaning up dir /path/to/bitcoin_func_test_XXXXXXX on exit 15020XX-XX-XXTXX:XX:XX.XXXXXXX TestFramework (INFO): Tests successful 151``` 152 153The following utility consolidates logs from the bitcoind nodes and the 154underlying `BitcoinTestFramework`: 155 156* `/path/to/bitcoin/test/functional/combine_logs.py 157 '/path/to/bitcoin_func_test_XXXXXXX'` 158 159## 6. Custom `TestShell` parameters 160 161The `TestShell` object initializes with the default settings inherited from the 162`BitcoinTestFramework` class. The user can override these in 163`TestShell.setup(key=value)`. 164 165**Note:** `TestShell.reset()` will reset test parameters to default values and 166can be called after the TestShell is shut down. 167 168| Test parameter key | Default Value | Description | 169|---|---|---| 170| `bind_to_localhost_only` | `True` | Binds bitcoind RPC services to `127.0.0.1` if set to `True`.| 171| `cachedir` | `"/path/to/bitcoin/test/cache"` | Sets the bitcoind datadir directory. | 172| `chain` | `"regtest"` | Sets the chain-type for the underlying test bitcoind processes. | 173| `configfile` | `"/path/to/bitcoin/test/config.ini"` | Sets the location of the test framework config file. | 174| `coveragedir` | `None` | Records bitcoind RPC test coverage into this directory if set. | 175| `loglevel` | `INFO` | Logs events at this level and higher. Can be set to `DEBUG`, `INFO`, `WARNING`, `ERROR` or `CRITICAL`. | 176| `nocleanup` | `False` | Cleans up temporary test directory if set to `True` during `shutdown`. | 177| `noshutdown` | `False` | Does not stop bitcoind instances after `shutdown` if set to `True`. | 178| `num_nodes` | `1` | Sets the number of initialized bitcoind processes. | 179| `perf` | False | Profiles running nodes with `perf` for the duration of the test if set to `True`. | 180| `rpc_timeout` | `60` | Sets the RPC server timeout for the underlying bitcoind processes. | 181| `setup_clean_chain` | `False` | A 200-block-long chain is initialized from cache by default. Instead, `setup_clean_chain` initializes an empty blockchain if set to `True`. | 182| `randomseed` | Random Integer | `TestShell.options.randomseed` is a member of `TestShell` which can be accessed during a test to seed a random generator. User can override default with a constant value for reproducible test runs. | 183| `supports_cli` | `False` | Whether the bitcoin-cli utility is compiled and available for the test. | 184| `tmpdir` | `"/var/folders/.../"` | Sets directory for test logs. Will be deleted upon a successful test run unless `nocleanup` is set to `True` | 185| `trace_rpc` | `False` | Logs all RPC calls if set to `True`. | 186| `usecli` | `False` | Uses the bitcoin-cli interface for all bitcoind commands instead of directly calling the RPC server. Requires `supports_cli`. | 187