github.com/aychain/blockbook@v0.1.1-0.20181121092459-6d1fc7e07c5b/docs/testing.md (about)

     1  # Testing
     2  
     3  There are two kinds of tests in Blockbook – unit tests and integration tests. Because integration tests require running
     4  back-end daemon so they can't be executed at every build. Blockbook's build system uses conditional compilation to
     5  distinguish which tests should be executed.
     6  
     7  There are several ways to run tests:
     8  
     9  * `make test` – run unit tests only (note that `make deb*` and `make all*` commands always run also *test* target)
    10  * `make test-integration` – run integration tests only
    11  * `make test-all` – run all tests above
    12  
    13  You can use Go's flag *-run* to filter which tests should be executed. Use *ARGS* variable, e.g.
    14  `make test-all ARGS="-run TestBitcoin"`.
    15  
    16  
    17  ## Unit tests
    18  
    19  Unit test file must start with constraint `// +build unittest` followed by blank line (constraints are described
    20  [here](https://golang.org/pkg/go/build/#hdr-Build_Constraints)).
    21  
    22  Every coin implementation must have unit tests. At least for parser. Usual test suite define real transaction data
    23  and try pack and unpack them. Specialities of particular coin are tested too. See examples in
    24  [bcashparser_test.go](/bchain/coins/bch/bcashparser_test.go),
    25  [bitcoinparser_test.go](/bchain/coins/btc/bitcoinparser_test.go) and
    26  [ethparser_test.go](/bchain/coins/eth/ethparser_test.go).
    27  
    28  
    29  ## Integration tests
    30  
    31  Integration tests test interface between either Blockbook's components or back-end services. Integration tests are
    32  located in *tests* directory and every test suite has its own package. Because RPC and synchronization are crucial
    33  components of Blockbook, it is mandatory that coin implementations have these integration tests defined. They are
    34  implemented in packages `blockbook/tests/rpc` and `blockbook/tests/sync` and both of them are declarative. For each coin
    35  there are test definition that enables particular tests of test suite and *testdata* file that contains test fixtures.
    36  
    37  Not every coin implementation support full set of back-end API so it is necessary define which tests of test suite
    38  are able to run. That is done in test definition file *blockbook/tests/tests.json*. Configuration is hierarchical and
    39  test implementations call each level as separate subtest. Go's *test* command allows filter tests to run by `-run` flag.
    40  It perfectly fits with layered test definitions. For example, you can:
    41  
    42  * run tests for single coin – `make test-integration ARGS="-run=TestIntegration/bitcoin/"`
    43  * run single test suite – `make test-integration ARGS="-run=TestIntegration//sync/"`
    44  * run single test – `make test-integration ARGS="-run=TestIntegration//sync/HandleFork"`
    45  * run tests for set of coins – `make test-integration ARGS="-run='TestIntegration/(bcash|bgold|bitcoin|dash|dogecoin|litecoin|vertcoin|zcash)/'"`
    46  
    47  Test fixtures are defined in *testdata* directory in package of particular test suite. They are separate JSON files named
    48  by coin. File schemes are very similar with verbose results of CLI tools and are described below. Integration tests
    49  follow the same concept, use live component or service and verify their results with fixtures.
    50  
    51  For simplicity, URLs and credentials of back-end services, where are tests going to connect, are loaded
    52  from *blockbook/configs/coins*, the same place from where are production configuration files generated. There are general
    53  URLs that link to *localhost*. If you need run tests against remote servers, there are few options how to do it:
    54  
    55  * temporarily change config
    56  * SSH tunneling – `ssh -nNT -L 8030:localhost:8030 remote-server`
    57  * HTTP proxy
    58  
    59  ### Synchronization integration tests
    60  
    61  Synchronization is crucial part of Blockbook and these tests test whether it is doing well. They sync few blocks from
    62  blockchain and verify them against fixtures. Ranges of blocks to sync are defined in fixtures.
    63  
    64  * `ConnectBlocks` – Calls *db.SyncWorker.connectBlocks*, a single-thread method that is called when a new block is detected.
    65     Sync blocks and checks whether blocks and transactions from fixtures are indexed.
    66  * `ConnectBlocksParallel` – Calls *db.SyncWorker.ConnectBlocksParallel*, a multi-thread method that is used during initial
    67     synchronization. Uses the same fixtures as ConnectBlocks.
    68  * `HandleFork` – Calls *db.SyncWorker.HandleFork* method that rolls back blockchain if a fork is detected. Test uses two
    69     sets of blocks with the same heights in fixtures. First set – with fake blocks – is synced initially, than *HandleFork*
    70     method is called and finally it is checked that index contain only blocks from second set – the real blocks. *Make
    71     sure that fake blocks have hashes of real blocks out of a sync range. It is important because Blockbook attempts to
    72     load these blocks and if it is unsuccessful the test fails. A good practice is use blocks with a height about 20 lower
    73     than `syncRanges.lower` and decreasing.*
    74  
    75  ### Back-end RPC integration tests
    76  
    77  This kind of tests test *bchain.BlockChain* implementation and its capability to communicate with back-end RPC.
    78  
    79  Tests listed below just call back-end RPC methods with parameters from fixture file and check results against same
    80  fixture file. So data in fixture file must be related together.
    81  
    82  * `GetBlockHash` – Calls *BlockChain.GetBlockHash* with height and checks returned hash.
    83  * `GetBlockHeader` – Calls *BlockChain.GetBlockHeader* with hash and check returned header. Note that only fields
    84     that are significant are *Hash* and *Height*, they are checked against fixtures. Scheme of transaction data in fixtures
    85     is very similar to verbose result of *getrawtransaction* command of CLI tools and can be copy-pasted with few
    86     modifications.
    87  * `GetBlock` – Calls *BlockChain.GetBlock* with hash and checks returned block (actually number of transactions and
    88     their txids).
    89  * `GetTransaction` – Calls *BlockChain.GetTransaction* with txid and checks result against transaction object, where
    90     *txid* is key and *transaction object* is value of *txDetails* object in fixture file.
    91  * `GetTransactionForMempool` – Calls *BlockChain.GetTransactionForMempool* that should be version of
    92     *BlockChain.GetTransaction* optimized for mempool. Implementation of test is similar.
    93  * `GetMempoolEntry` – Calls *BlockChain.GetMempoolEntry* and checks result. Because mempool is living structure it
    94     tries to load entry for random transaction in mempool repeatedly.
    95  * `EstimateSmartFee` – Calls *BlockChain.EstimateSmartFee* for few numbers of blocks and checks if returned fee is
    96     non-negative.
    97  * `EstimateFee` – Calls *BlockChain.EstimateFee*; implementation is same as *EstimateSmartFee*.
    98  * `GetBestBlockHash` – Calls *BlockChain.GetBestBlockHash* and verifies that returned hash matches the really last
    99     block.
   100  * `GetBestBlockHeight` – Calls *BlockChain.GetBestBlockHeight* and verifies that returned height matches the really
   101     last block.
   102  * `MempoolSync` – Synchronize *BlockChain*'s mempool and verify if sync was successful.