Merge pull request #139 from pipermerriam/piper/add-tester-module

add testing module
This commit is contained in:
Piper Merriam 2016-12-30 12:57:34 -07:00 committed by GitHub
commit 6b6d90ea33
9 changed files with 168 additions and 2 deletions

55
docs/web3.testing.rst Normal file
View File

@ -0,0 +1,55 @@
Testing API
===========
.. py:module:: web3.testing
.. py:currentmodule:: web3.testing
.. py:class:: Testing
The ``web3.testing`` object exposes methods to interact with non-standard RPC
APIs that are only available under the python ``eth-testrpc`` package.
Methods
-------
The following methods are available on the ``web3.testing`` namespace.
.. py:method:: Testing.timeTravel(timestamp)
* Delegates to ``testing_timeTravel`` RPC Method
Advances the test blockchain one block setting the new block's timestamp to
the provided integer timestamp.
.. py:method:: Testing.mine(num_blocks=1)
* Delegates to ``evm_mine`` RPC Method
Mines ``num_blocks`` new blocks.
.. py:method:: Testing.snapshot()
* Delegates to ``evm_snapshot`` RPC Method
Takes a snapshot of the current EVM state and returns an integer that can
be used with the ``revert`` method to restore the EVM to this state.
.. py:method:: Testing.revert(snapshot_idx=None)
* Delegates to ``evm_revert`` RPC Method
If no ``snapshot_idx`` is provided this will revert the EVM to the most
recent snapshot. Otherwise reverts the EVM to the snapshot indicated by
the provided ``snapshot_idx``
.. py:method:: Testing.reset()
* Delegates to ``evm_reset`` RPC Method
Reset the EVM back to the genesis state.

View File

@ -1,7 +1,7 @@
pytest>=2.8.2
pytest-pythonpath>=0.3
tox>=1.8.0
eth-testrpc>=0.9.0
eth-testrpc>=0.9.3
py-geth>=1.4.0
ethereum>=1.5.2
secp256k1>=0.13.1

View File

@ -33,7 +33,7 @@ setup(
"pylru>=1.0.9",
],
extras_require={
'Tester': ["eth-testrpc>=0.9.0"],
'Tester': ["eth-testrpc>=0.9.3"],
},
py_modules=['web3'],
license="MIT",

View File

@ -0,0 +1,22 @@
def test_testing_mine_single_block(web3):
web3.testing.mine()
before_mining_block = web3.eth.getBlock("latest")
web3.testing.mine()
after_mining_block = web3.eth.getBlock("latest")
assert after_mining_block['number'] - before_mining_block['number'] == 1
def test_testing_mine_multiple_blocks(web3):
web3.testing.mine()
before_mining_block = web3.eth.getBlock("latest")
web3.testing.mine(5)
after_mining_block = web3.eth.getBlock("latest")
assert after_mining_block['number'] - before_mining_block['number'] == 5

View File

@ -0,0 +1,47 @@
def test_snapshot_revert_to_latest_snapshot(web3):
web3.testing.mine(5)
block_before_snapshot = web3.eth.getBlock("latest")
snapshot_idx = web3.testing.snapshot()
block_after_snapshot = web3.eth.getBlock("latest")
web3.testing.mine(3)
block_after_mining = web3.eth.getBlock("latest")
web3.testing.revert()
block_after_revert = web3.eth.getBlock("latest")
assert block_after_mining['number'] > block_before_snapshot['number']
assert block_before_snapshot['hash'] == block_after_snapshot['hash']
assert block_after_snapshot['hash'] == block_after_revert['hash']
def test_snapshot_revert_to_specific(web3):
web3.testing.mine(5)
block_before_snapshot = web3.eth.getBlock("latest")
snapshot_idx = web3.testing.snapshot()
block_after_snapshot = web3.eth.getBlock("latest")
web3.testing.mine()
web3.testing.snapshot()
web3.testing.mine()
web3.testing.snapshot()
web3.testing.mine()
web3.testing.snapshot()
block_after_mining = web3.eth.getBlock("latest")
web3.testing.revert(snapshot_idx)
block_after_revert = web3.eth.getBlock("latest")
assert block_after_mining['number'] > block_before_snapshot['number']
assert block_before_snapshot['hash'] == block_after_snapshot['hash']
assert block_after_snapshot['hash'] == block_after_revert['hash']

View File

@ -0,0 +1,9 @@
def test_time_traveling(web3):
current_block_time = web3.eth.getBlock("pending")['timestamp']
time_travel_to = current_block_time + 12345
web3.testing.timeTravel(time_travel_to)
latest_block_time = web3.eth.getBlock("pending")['timestamp']
assert latest_block_time >= time_travel_to

View File

@ -24,6 +24,7 @@ commands=
db: py.test {posargs:tests/db-module}
managers: py.test {posargs:tests/managers}
personal: py.test {posargs:tests/personal-module}
testing: py.test {posargs:tests/testing-module}
utilities: py.test {posargs:tests/utilities}
deps =
-r{toxinidir}/requirements-dev.txt

View File

@ -9,6 +9,7 @@ from web3.personal import Personal
from web3.shh import Shh
from web3.txpool import TxPool
from web3.version import Version
from web3.testing import Testing
from web3.iban import Iban
@ -100,6 +101,7 @@ class Web3(object):
self.txpool = TxPool(self)
self.miner = Miner(self)
self.admin = Admin(self)
self.testing = Testing(self)
def setProvider(self, provider):
self._requestManager.setProvider(provider)

30
web3/testing.py Normal file
View File

@ -0,0 +1,30 @@
from web3.utils.encoding import (
to_decimal,
)
from web3.utils.functional import (
apply_formatters_to_return,
)
class Testing(object):
def __init__(self, web3):
self.web3 = web3
def timeTravel(self, timestamp):
return self.web3._requestManager.request_blocking("testing_timeTravel", [timestamp])
def mine(self, num_blocks=1):
return self.web3._requestManager.request_blocking("evm_mine", [num_blocks])
@apply_formatters_to_return(to_decimal)
def snapshot(self):
return self.web3._requestManager.request_blocking("evm_snapshot", [])
def reset(self):
return self.web3._requestManager.request_blocking("evm_reset", [])
def revert(self, snapshot_idx=None):
if snapshot_idx is None:
return self.web3._requestManager.request_blocking("evm_revert", [])
else:
return self.web3._requestManager.request_blocking("evm_revert", [snapshot_idx])