bitcoin-s/docs/next/testkit/testkit.html
Docusaurus bot a727012a57 Deploy website
Deploy website version based on 2e1b4d0491
2020-10-10 03:48:36 +00:00

215 lines
No EOL
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Testkit · bitcoin-s</title><meta name="viewport" content="width=device-width"/><meta name="generator" content="Docusaurus"/><meta name="description" content="## Philosphy of Testkit"/><meta name="docsearch:version" content="next"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="Testkit · bitcoin-s"/><meta property="og:type" content="website"/><meta property="og:url" content="https://bitcoin-s.org/"/><meta property="og:description" content="## Philosphy of Testkit"/><meta property="og:image" content="https://bitcoin-s.org/img/undraw_online.svg"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://bitcoin-s.org/img/undraw_tweetstorm.svg"/><link rel="shortcut icon" href="/img/favicon.ico"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"/><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-61958686-2', 'auto');
ga('send', 'pageview');
</script><link rel="stylesheet" href="/css/code-block-buttons.css"/><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js"></script><script type="text/javascript" src="https://fonts.googleapis.com/css?family=Montserrat:500"></script><script type="text/javascript" src="https://www.googletagmanager.com/gtag/js?id=UA-61958686-2"></script><script type="text/javascript" src="/js/code-block-buttons.js"></script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/favicon.ico" alt="bitcoin-s"/><h2 class="headerTitleWithLogo">bitcoin-s</h2></a><a href="/versions"><h3>next</h3></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class="siteNavGroupActive"><a href="/docs/next/core/core-intro" target="_self">Docs</a></li><li class=""><a href="/api/org/bitcoins" target="_self">API</a></li><li class=""><a href="/help" target="_self">Help</a></li><li class="navSearchWrapper reactNavSearchWrapper"><input type="text" id="search_input_react" placeholder="Search" title="Search"/></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i></i><span>Testkit</span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle">Getting Started</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/getting-started">Intro and Getting Started</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Getting Setup</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/getting-setup">Getting Bitcoin-S installed on your machine</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Applications</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/applications/cli">CLI</a></li><li class="navListItem"><a class="navItem" href="/docs/next/applications/server">Application Server</a></li><li class="navListItem"><a class="navItem" href="/docs/next/applications/gui">GUI</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Chain</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/chain/chain">Blockchain Verification</a></li><li class="navListItem"><a class="navItem" href="/docs/next/chain/filter-sync">Syncing Blockfilters</a></li><li class="navListItem"><a class="navItem" href="/docs/next/chain/chain-query-api">Chain Query API</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Configuration</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/config/configuration">Application Configuration</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Core Module</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/core/core-intro">Core Module</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/addresses">Generating Addresses</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/hd-keys">HD Key Generation</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/adding-spks">Adding New Script Types</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/spending-info">Signing Transactions</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/psbts">Partially Signed Bitcoin Transactions</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/txbuilder">TxBuilder Example</a></li><li class="navListItem"><a class="navItem" href="/docs/next/core/lightning-network">Lightning Network Data Types</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Crypto Module</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/crypto/crypto-intro">Crypto Module</a></li><li class="navListItem"><a class="navItem" href="/docs/next/crypto/sign">Sign API</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Fee Provider</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/fee-provider/fee-provider">Fee Provider</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Key Manager</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/key-manager/key-manager">Key Manager</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Node</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/node/node">Light Client</a></li><li class="navListItem"><a class="navItem" href="/docs/next/node/node-api">Node API</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Wallet</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/wallet/wallet">Wallet</a></li><li class="navListItem"><a class="navItem" href="/docs/next/wallet/wallet-callbacks">Wallet Callbacks</a></li><li class="navListItem"><a class="navItem" href="/docs/next/wallet/wallet-get-address">Wallet Get Address APIs</a></li><li class="navListItem"><a class="navItem" href="/docs/next/wallet/address-tagging">Address and UTXO tagging</a></li><li class="navListItem"><a class="navItem" href="/docs/next/wallet/dlc">Executing A DLC with Bitcoin-S</a></li><li class="navListItem"><a class="navItem" href="/docs/next/wallet/wallet-rescan">Wallet Rescans</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">RPC Clients</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/rpc/rpc-clients-intro">Introduction</a></li><li class="navListItem"><a class="navItem" href="/docs/next/rpc/rpc-eclair">Eclair</a></li><li class="navListItem"><a class="navItem" href="/docs/next/rpc/rpc-bitcoind">bitcoind/Bitcoin Core</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Secp256k1</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/secp256k1/secp256k1">Secp256k1</a></li><li class="navListItem"><a class="navItem" href="/docs/next/secp256k1/jni-modify">Adding to Secp256k1 JNI</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Testkit</h3><ul class=""><li class="navListItem navListItemActive"><a class="navItem" href="/docs/next/testkit/testkit">Testkit</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">DLC Oracle</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/oracle/oracle-server">Oracle Server</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Contributing</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/contributing">Contributing</a></li><li class="navListItem"><a class="navItem" href="/docs/next/contributing-website">Contributing to the website</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle">Security</h3><ul class=""><li class="navListItem"><a class="navItem" href="/docs/next/security">Security</a></li></ul></div></div></section></div><script>
var coll = document.getElementsByClassName('collapsible');
var checkActiveCategory = true;
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*');
if (checkActiveCategory){
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')){
coll[i].nextElementSibling.classList.toggle('hide');
coll[i].childNodes[1].classList.toggle('rotate');
checkActiveCategory = false;
break;
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1];
arrow.classList.toggle('rotate');
var content = this.nextElementSibling;
content.classList.toggle('hide');
});
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
createToggler('#tocToggler', 'body', 'tocActive');
var headings = document.querySelector('.toc-headings');
headings && headings.addEventListener('click', function(event) {
var el = event.target;
while(el !== headings){
if (el.tagName === 'A') {
document.body.classList.remove('tocActive');
break;
} else{
el = el.parentNode;
}
}
}, false);
function createToggler(togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector);
var target = document.querySelector(targetSelector);
if (!toggler) {
return;
}
toggler.onclick = function(event) {
event.preventDefault();
target.classList.toggle(className);
};
}
});
</script></nav></div><div class="container mainContainer docsContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/bitcoin-s/bitcoin-s/blob/master/docs/testkit/testkit.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 id="__docusaurus" class="postHeaderTitle">Testkit</h1></header><article><div><span><h2><a class="anchor" aria-hidden="true" id="philosphy-of-testkit"></a><a href="#philosphy-of-testkit" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Philosphy of Testkit</h2>
<p>The high level of of the bitcoin-s testkit is to mimic and provide functionality to test 3rd party applications.</p>
<p>There are other examples of these in the Scala ecosystem like the <code>akka-testkit</code> and <code>slick-testkit</code>.</p>
<p>We use this testkit to test bitcoin-s it self.</p>
<h3><a class="anchor" aria-hidden="true" id="testkit-for-bitcoind"></a><a href="#testkit-for-bitcoind" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testkit for bitcoind</h3>
<p>This gives the ability to create and destroy <code>bitcoind</code> on the underlying operating system to test against.</p>
<p>Make sure you have run <code>sbt downloadBitcoind</code> before running this example, as you need access to the bitcoind binaries.</p>
<p>Our <a href="/api/org/bitcoins/rpc/client/common/BitcoindRpcClient">BitcoindRpcClient</a> is tested with the functionality provided in the testkit.
A quick example of a useful utility method is <a href="/api/org/bitcoins/testkit/rpc/BitcoindRpcTestUtil">BitcoindRpcTestUtil.startedBitcoindRpcClient()</a>.
This spins up a bitcoind regtest instance on machine and generates 101 blocks on that node.</p>
<p>This gives you the ability to start spending money immediately with that bitcoind node.</p>
<pre><code class="hljs css language-scala"><span class="hljs-keyword">implicit</span> <span class="hljs-keyword">val</span> system = <span class="hljs-type">ActorSystem</span>(<span class="hljs-string">"bitcoind-testkit-example"</span>)
<span class="hljs-keyword">implicit</span> <span class="hljs-keyword">val</span> ec = system.dispatcher
<span class="hljs-comment">//pick our bitcoind version we want to spin up</span>
<span class="hljs-comment">//you can pick older versions if you want</span>
<span class="hljs-comment">//we support versions 16-19</span>
<span class="hljs-keyword">val</span> bitcoindV = <span class="hljs-type">BitcoindVersion</span>.<span class="hljs-type">V19</span>
<span class="hljs-comment">//create an instance</span>
<span class="hljs-keyword">val</span> instance = <span class="hljs-type">BitcoindRpcTestUtil</span>.instance(versionOpt = <span class="hljs-type">Some</span>(bitcoindV))
<span class="hljs-comment">//now let's create an rpc client off of that instance</span>
<span class="hljs-keyword">val</span> bitcoindRpcClientF = <span class="hljs-type">BitcoindRpcTestUtil</span>.startedBitcoindRpcClient(instance)
<span class="hljs-comment">//yay! it's started. Now you can run tests against this.</span>
<span class="hljs-comment">//let's just grab the block count for an example</span>
<span class="hljs-keyword">val</span> blockCountF = <span class="hljs-keyword">for</span> {
bitcoind &lt;- bitcoindRpcClientF
count &lt;- bitcoind.getBlockCount
} <span class="hljs-keyword">yield</span> {
<span class="hljs-comment">//run a test against the block count</span>
assert(count &gt; <span class="hljs-number">0</span>, <span class="hljs-string">s"Block count was not more than zero!"</span>)
}
<span class="hljs-comment">//when you are done, don't forget to destroy it! Otherwise it will keep running on the underlying os</span>
<span class="hljs-keyword">val</span> stoppedF = <span class="hljs-keyword">for</span> {
rpc &lt;- bitcoindRpcClientF
_ &lt;- blockCountF
stopped &lt;- <span class="hljs-type">BitcoindRpcTestUtil</span>.stopServers(<span class="hljs-type">Vector</span>(rpc))
} <span class="hljs-keyword">yield</span> stopped
</code></pre>
<p>For more information on how the bitcoind rpc client works, see our <a href="/docs/next/rpc/rpc-bitcoind">bitcoind rpc docs</a></p>
<h3><a class="anchor" aria-hidden="true" id="testkit-for-eclair"></a><a href="#testkit-for-eclair" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testkit for eclair</h3>
<p>We have similar utility methods for eclair. Eclair's testkit requires a bitcoind running (which we can spin up thanks to our bitcoind testkit).</p>
<p>Here is an example of spinning up an eclair lightning node, that is connected to a bitcoind and testing your lightning application.</p>
<p>Make sure to run <code>sbt downloadBitcoind downloadEclair</code> before running this so you have access to the underlying eclair binares</p>
<pre><code class="hljs css language-scala"><span class="hljs-comment">//Steps:</span>
<span class="hljs-comment">//1. Open and confirm channel on the underlying blockchain (regtest)</span>
<span class="hljs-comment">//2. pay an invoice</span>
<span class="hljs-comment">//3. Await until the payment is processed</span>
<span class="hljs-comment">//4. assert the node has received the payment</span>
<span class="hljs-comment">//5. cleanup</span>
<span class="hljs-keyword">implicit</span> <span class="hljs-keyword">val</span> system = <span class="hljs-type">ActorSystem</span>(<span class="hljs-string">"eclair-testkit-example"</span>)
<span class="hljs-keyword">implicit</span> <span class="hljs-keyword">val</span> ec = system.dispatcher
<span class="hljs-comment">//we need a bitcoind to connect eclair nodes to</span>
<span class="hljs-keyword">lazy</span> <span class="hljs-keyword">val</span> bitcoindRpcClientF: <span class="hljs-type">Future</span>[<span class="hljs-type">BitcoindRpcClient</span>] = {
<span class="hljs-keyword">for</span> {
cli &lt;- <span class="hljs-type">EclairRpcTestUtil</span>.startedBitcoindRpcClient()
<span class="hljs-comment">// make sure we have enough money to open channels</span>
address &lt;- cli.getNewAddress
_ &lt;- cli.generateToAddress(<span class="hljs-number">200</span>, address)
} <span class="hljs-keyword">yield</span> cli
}
<span class="hljs-comment">//let's create two eclair nodes now</span>
<span class="hljs-keyword">val</span> clientF = <span class="hljs-keyword">for</span> {
bitcoind &lt;- bitcoindRpcClientF
e &lt;- <span class="hljs-type">EclairRpcTestUtil</span>.randomEclairClient(<span class="hljs-type">Some</span>(bitcoind))
} <span class="hljs-keyword">yield</span> e
<span class="hljs-keyword">val</span> otherClientF = <span class="hljs-keyword">for</span> {
bitcoind &lt;- bitcoindRpcClientF
e &lt;- <span class="hljs-type">EclairRpcTestUtil</span>.randomEclairClient(<span class="hljs-type">Some</span>(bitcoind))
} <span class="hljs-keyword">yield</span> e
<span class="hljs-comment">//great, setup done! Let's run the test</span>
<span class="hljs-comment">//to verify we can send a payment over the channel</span>
<span class="hljs-keyword">for</span> {
client &lt;- clientF
otherClient &lt;- otherClientF
_ &lt;- <span class="hljs-type">EclairRpcTestUtil</span>.openAndConfirmChannel(clientF, otherClientF)
invoice &lt;- otherClient.createInvoice(<span class="hljs-string">"abc"</span>, <span class="hljs-number">50.</span>msats)
info &lt;- otherClient.getInfo
_ = assert(info.nodeId == invoice.nodeId)
infos &lt;- client.getSentInfo(invoice.lnTags.paymentHash.hash)
_ = assert(infos.isEmpty)
paymentId &lt;- client.payInvoice(invoice)
_ &lt;- <span class="hljs-type">EclairRpcTestUtil</span>.awaitUntilPaymentSucceeded(client, paymentId)
sentInfo &lt;- client.getSentInfo(invoice.lnTags.paymentHash.hash)
} <span class="hljs-keyword">yield</span> {
assert(sentInfo.head.amount == <span class="hljs-number">50.</span>msats)
}
<span class="hljs-comment">//don't forget to shutdown everything!</span>
<span class="hljs-keyword">val</span> stop1F = clientF.map(c =&gt; <span class="hljs-type">EclairRpcTestUtil</span>.shutdown(c))
<span class="hljs-keyword">val</span> stop2F = otherClientF.map(o =&gt; <span class="hljs-type">EclairRpcTestUtil</span>.shutdown(o))
<span class="hljs-keyword">val</span> stoppedBitcoindF = <span class="hljs-keyword">for</span> {
bitcoind &lt;- bitcoindRpcClientF
_ &lt;- <span class="hljs-type">BitcoindRpcTestUtil</span>.stopServers(<span class="hljs-type">Vector</span>(bitcoind))
} <span class="hljs-keyword">yield</span> ()
<span class="hljs-keyword">val</span> resultF = <span class="hljs-keyword">for</span> {
_ &lt;- stop1F
_ &lt;- stop2F
_ &lt;- stoppedBitcoindF
_ &lt;- system.terminate()
} <span class="hljs-keyword">yield</span> ()
<span class="hljs-type">Await</span>.result(resultF, <span class="hljs-number">180.</span>seconds)
</code></pre>
<h3><a class="anchor" aria-hidden="true" id="testkit-for-core"></a><a href="#testkit-for-core" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testkit for core</h3>
<p>The testkit functionality for our core module primary consists of generators for property based tests.</p>
<p>A generator is a piece of code that generates a random object for a data strucutre -- such as a <code>Transaction</code>.</p>
<p>There is also a robust set of generators available in the <a href="../../testkit/src/main/scala/org/bitcoins/testkit/core/gen">org.bitcoins.testkit.gen</a> package.
This allows you to integrate property based testing into your library and feel confident about implementing your application specific logic correctly.</p>
<p>You can see examples of us using these generators inside of testkit in our <a href="../../core-test/src/test/scala/org/bitcoins/core/crypto/ECPrivateKeyTest.scala">Private Key test cases</a></p>
<h3><a class="anchor" aria-hidden="true" id="other-modules"></a><a href="#other-modules" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Other modules</h3>
<p>You may find useful testkit functionality for other modules here</p>
<ol>
<li><a href="/api/org/bitcoins/testkit/chain/ChainUnitTest">Chain</a></li>
<li><a href="/api/org/bitcoins/testkit/keymanager/KeyManagerApiUnitTest">Key Manager</a></li>
<li><a href="/api/org/bitcoins/testkit/wallet/BitcoinSWalletTest">Wallet</a></li>
<li><a href="/api/org/bitcoins/testkit/node/NodeUnitTest">Node</a></li>
</ol>
<p>In general, you will find constructors and destructors of fixtures that can be useful when testing your applications
if yo uare using any of those modules.</p>
</span></div></article></div><div class="docs-prevnext"><a class="docs-prev button" href="/docs/next/secp256k1/jni-modify"><span class="arrow-prev"></span><span>Adding to Secp256k1 JNI</span></a><a class="docs-next button" href="/docs/next/oracle/oracle-server"><span>Oracle Server</span><span class="arrow-next"></span></a></div></div></div><nav class="onPageNav"><ul class="toc-headings"><li><a href="#philosphy-of-testkit">Philosphy of Testkit</a><ul class="toc-headings"><li><a href="#testkit-for-bitcoind">Testkit for bitcoind</a></li><li><a href="#testkit-for-eclair">Testkit for eclair</a></li><li><a href="#testkit-for-core">Testkit for core</a></li><li><a href="#other-modules">Other modules</a></li></ul></li></ul></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><a href="/" class="nav-home"><img src="/img/favicon.ico" alt="bitcoin-s" width="66" height="58"/></a><div><h5>Docs</h5><a href="/docs/en/getting-started">Getting Started</a><a href="/docs/en/core/core-intro">Guides</a><a href="/api/org/bitcoins">API Reference</a></div><div><h5>Community</h5><a href="/en/users.html">User Showcase</a><a href="https://join.slack.com/t/suredbits/shared_invite/zt-eavycu0x-WQL7XOakzQo8tAy7jHHZUw" target="_blank" rel="noreferrer noopener">Slack</a><a href="https://gitter.im/bitcoin-s-core/">Gitter chat</a></div><div><h5>More</h5><a href="https://github.com/bitcoin-s/bitcoin-s">GitHub</a><a class="github-button" href="https://github.com/bitcoin-s/bitcoin-s" data-icon="octicon-star" data-count-href="/bitcoin-s/bitcoin-s-core/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star this project on GitHub">Star</a></div></section><section class="copyright">Copyright © 2020 Suredbits &amp; the bitcoin-s developers</section></footer></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>
document.addEventListener('keyup', function(e) {
if (e.target !== document.body) {
return;
}
// keyCode for '/' (slash)
if (e.keyCode === 191) {
const search = document.getElementById('search_input_react');
search && search.focus();
}
});
</script><script>
var search = docsearch({
apiKey: '0a510688bf8448e19aeb380377d328d3',
indexName: 'bitcoin-s',
inputSelector: '#search_input_react'
});
</script></body></html>