diff --git a/.gitignore b/.gitignore
index 84e345ad8..a3ae1ca18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ ChangeLog
 devenv/*
 .coverage
 coverage.xml
+.testrepository
diff --git a/.testr.conf b/.testr.conf
new file mode 100644
index 000000000..b8a64a79d
--- /dev/null
+++ b/.testr.conf
@@ -0,0 +1,4 @@
+[DEFAULT] 
+test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 ${PYTHON:-python} -m subunit.run discover -s teeth_agent/tests/ -p "*.py" $LISTOPT $IDOPTION 
+test_id_option=--load-list $IDFILE 
+test_list_option=--list
diff --git a/.travis.yml b/.travis.yml
index a91034f4d..8c35f9720 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,15 @@
 language: python
 python: 2.7
+env:
+- TOX_ENV=py26
+- TOX_ENV=py27
+- TOX_ENV=pep8
+
 install:
-  - pip install tox
+- pip install tox
 script:
-  - tox
-branches:
-  only:
-    - master
+- tox -vv -e $TOX_ENV
+
 notifications:
   irc:
     channels:
diff --git a/dev-requirements.txt b/dev-requirements.txt
deleted file mode 100644
index 5aa4d7e7c..000000000
--- a/dev-requirements.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-pep257==0.2.4
-plumbum==1.3.0
-pep8==1.4.6
-pyflakes==0.7.3
-junitxml==0.7
-python-subunit==0.0.15
-mock==1.0.1
-coverage==3.6
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index c38e4e3e9..fa35225cc 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,3 +3,4 @@ requests==2.0.0
 cherrypy==3.2.4
 stevedore==0.14
 -e git+https://github.com/racker/teeth-rest.git@e876c0fddd5ce2f5223ab16936f711b0d57e19c4#egg=teeth_rest
+structlog
\ No newline at end of file
diff --git a/setup.cfg b/setup.cfg
index 11fae0566..c0034a15c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -24,3 +24,19 @@ teeth_agent.modes =
 
 teeth_agent.hardware_managers =
     generic = teeth_agent.hardware:GenericHardwareManager
+
+[pbr]
+autodoc_index_modules = True
+
+[build_sphinx]
+all_files = 1
+build-dir = doc/build
+source-dir = doc/source
+
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
+[wheel]
+universal = 1
\ No newline at end of file
diff --git a/teeth_agent/cmd/agent.py b/teeth_agent/cmd/agent.py
index bdfa8d41d..6e0ca6988 100644
--- a/teeth_agent/cmd/agent.py
+++ b/teeth_agent/cmd/agent.py
@@ -17,7 +17,7 @@ limitations under the License.
 import argparse
 
 from teeth_agent import agent
-from teeth_agent import logging
+from teeth_agent import log
 
 
 def run():
@@ -40,7 +40,7 @@ def run():
                         help='The port to listen on')
 
     args = parser.parse_args()
-    logging.configure()
+    log.configure()
     agent.build_agent(args.api_url,
                       args.listen_host,
                       args.listen_port).run()
diff --git a/teeth_agent/logging.py b/teeth_agent/log.py
similarity index 100%
rename from teeth_agent/logging.py
rename to teeth_agent/log.py
diff --git a/teeth_agent/shell/__init__.py b/teeth_agent/shell/__init__.py
new file mode 100644
index 000000000..e6d79b5bc
--- /dev/null
+++ b/teeth_agent/shell/__init__.py
@@ -0,0 +1 @@
+__author__ = 'joshgachnang'
diff --git a/teeth_agent/tests/logging.py b/teeth_agent/tests/log.py
similarity index 90%
rename from teeth_agent/tests/logging.py
rename to teeth_agent/tests/log.py
index fc8fde34e..0f21c75ec 100644
--- a/teeth_agent/tests/logging.py
+++ b/teeth_agent/tests/log.py
@@ -17,7 +17,7 @@ limitations under the License.
 import structlog
 import unittest
 
-import teeth_agent.logging
+import teeth_agent.log
 
 
 def _return_event_processor(logger, method, event):
@@ -26,7 +26,7 @@ def _return_event_processor(logger, method, event):
 
 class EventLogger(unittest.TestCase):
     def test_format_event_basic(self):
-        processors = [teeth_agent.logging._format_event,
+        processors = [teeth_agent.log._format_event,
                       _return_event_processor]
         structlog.configure(processors=processors)
         log = structlog.wrap_logger(structlog.ReturnLogger())
@@ -37,7 +37,7 @@ class EventLogger(unittest.TestCase):
         """Check that we get an exception if you don't provide enough keys to
         format a log message requiring format
         """
-        processors = [teeth_agent.logging._format_event,
+        processors = [teeth_agent.log._format_event,
                       _return_event_processor]
         structlog.configure(processors=processors)
         log = structlog.wrap_logger(structlog.ReturnLogger())
diff --git a/test-requirements.txt b/test-requirements.txt
index ad2786ed5..0f0b5c69a 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,5 +1,8 @@
-mock
-httmock
-coverage
-nose
-hacking
+hacking>=0.8.0,<0.9
+coverage>=3.6
+discover
+mock>=1.0
+testrepository>=0.0.18
+testtools>=0.9.34
+python-subunit>=0.0.18
+httmock
\ No newline at end of file
diff --git a/tox.ini b/tox.ini
index 3e8f68a98..504944d06 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,18 +1,38 @@
 [tox]
-envlist = flake8, unit
+minversion = 1.6
+skipsdist = True
+envlist = py26,py27,pep8
 
 [testenv]
-deps =
-    -rrequirements.txt
-    -rtest-requirements.txt
-
-[testenv:flake8]
-commands = flake8 teeth_agent
-
-[testenv:unit]
-commands =
-    nosetests --all-modules --with-coverage --cover-package=teeth_agent --cover-xml teeth_agent
-
-[testenv:devenv]
-envdir = devenv
 usedevelop = True
+install_command = pip install --allow-external -U {opts} {packages}
+setenv = VIRTUAL_ENV={envdir}
+deps = -r{toxinidir}/requirements.txt
+       -r{toxinidir}/test-requirements.txt
+commands =
+  python setup.py testr --slowest --testr-args='{posargs:}'
+
+[tox:jenkins]
+downloadcache = ~/cache/pip
+
+[testenv:pep8]
+commands =
+  flake8 {posargs:teeth_agent}
+
+[testenv:cover]
+setenv = VIRTUAL_ENV={envdir}
+commands =
+  python setup.py testr --coverage {posargs:teeth_agent}
+
+[testenv:venv]
+commands = {posargs:}
+
+[flake8]
+# E711: ignored because it is normal to use "column == None" in sqlalchemy
+
+ignore = E12,E711
+builtins = _
+exclude =  .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,*ironic/nova*,tools
+
+[hacking]
+import_exceptions = ironic.openstack.common.gettextutils._,testtools.matchers