Skip to content

Commit

Permalink
Merge pull request #139 from pipermerriam/piper/add-tester-module
Browse files Browse the repository at this point in the history
add testing module
  • Loading branch information
pipermerriam committed Dec 30, 2016
2 parents 6410d2a + e298a81 commit 6b6d90e
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 2 deletions.
55 changes: 55 additions & 0 deletions docs/web3.testing.rst
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"pylru>=1.0.9",
],
extras_require={
'Tester': ["eth-testrpc>=0.9.0"],
'Tester': ["eth-testrpc>=0.9.3"],
},
py_modules=['web3'],
license="MIT",
Expand Down
22 changes: 22 additions & 0 deletions tests/testing-module/test_testing_mine.py
Original file line number Diff line number Diff line change
@@ -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
47 changes: 47 additions & 0 deletions tests/testing-module/test_testing_snapshot_and_revert.py
Original file line number Diff line number Diff line change
@@ -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']
9 changes: 9 additions & 0 deletions tests/testing-module/test_testing_timeTravel.py
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions web3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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

Expand Down Expand Up @@ -100,6 +101,7 @@ def __init__(self, provider):
self.txpool = TxPool(self)
self.miner = Miner(self)
self.admin = Admin(self)
self.testing = Testing(self)

def setProvider(self, provider):
self._requestManager.setProvider(provider)
Expand Down
30 changes: 30 additions & 0 deletions web3/testing.py
Original file line number Diff line number Diff line change
@@ -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])

0 comments on commit 6b6d90e

Please sign in to comment.