diff --git a/src/python/grpcio/.gitignore b/src/python/grpcio/.gitignore
index b5db3b3cfb4dc6b618554c55cc1118f82a3b02ec..6f3d8673e7ac8612f1973a6e690f5df60bac82e6 100644
--- a/src/python/grpcio/.gitignore
+++ b/src/python/grpcio/.gitignore
@@ -9,6 +9,7 @@ dist/
 .coverage
 .coverage.*
 .cache/
+.tox/
 nosetests.xml
 doc/
 _grpcio_metadata.py
diff --git a/src/python/grpcio/tox.ini b/src/python/grpcio/tox.ini
new file mode 100644
index 0000000000000000000000000000000000000000..9acc4d65d81ef14a0edd78e502f680e83e2cd0c0
--- /dev/null
+++ b/src/python/grpcio/tox.ini
@@ -0,0 +1,21 @@
+# Tox (http://tox.testrun.org/) is a tool for running tests
+# in multiple virtualenvs. This configuration file will run the
+# test suite on all supported python versions. To use it, "pip install tox"
+# and then run "tox" from this directory.
+
+[tox]
+skipsdist = true
+envlist = py27
+
+[testenv]
+commands =
+    {envpython} setup.py build_py
+    {envpython} setup.py test
+    coverage combine
+    coverage report --include='grpc/*' --omit='grpc/framework/alpha/*','grpc/early_adopter/*','grpc/framework/base/*','grpc/framework/face/*'
+deps =
+    cython
+    coverage
+    oauth2client
+    protobuf
+passenv = *
diff --git a/tools/jenkins/grpc_jenkins_slave/Dockerfile b/tools/jenkins/grpc_jenkins_slave/Dockerfile
index 5b8c24c076ca217204a539a5109f4f24151b8b66..916e5e83fb572628c58ff899eab4133682e5674e 100644
--- a/tools/jenkins/grpc_jenkins_slave/Dockerfile
+++ b/tools/jenkins/grpc_jenkins_slave/Dockerfile
@@ -131,7 +131,7 @@ RUN apt-get update && apt-get install -y \
 # Install Python packages from PyPI
 RUN pip install pip --upgrade
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2 tox
 
 # For sanity test
 RUN pip install simplejson mako
diff --git a/tools/run_tests/build_python.sh b/tools/run_tests/build_python.sh
index c6396c85b1579184b4ee7f4f65a9c9d0003ab37b..7db14ce9d127444917ea670dea41a5488735671b 100755
--- a/tools/run_tests/build_python.sh
+++ b/tools/run_tests/build_python.sh
@@ -35,35 +35,13 @@ cd $(dirname $0)/../..
 
 ROOT=`pwd`
 GRPCIO=$ROOT/src/python/grpcio
-
-# Builds the testing environment.
-make_virtualenv() {
-  virtualenv_name="python"$1"_virtual_environment"
-  if [ ! -d $virtualenv_name ]
-  then
-    # Build the entire virtual environment
-    virtualenv -p `which "python"$1` $virtualenv_name
-    source $virtualenv_name/bin/activate
-
-    cd $GRPCIO
-    pip install -r requirements.txt
-  else
-    source $virtualenv_name/bin/activate
-
-    cd $GRPCIO
-    pip install -U -r requirements.txt
-  fi
-
-  export LD_LIBRARY_PATH=$ROOT/libs/$CONFIG
-  export DYLD_LIBRARY_PATH=$ROOT/libs/$CONFIG
-  export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
-  export CFLAGS="-I$ROOT/include -std=c89"
-  export LDFLAGS="-L$ROOT/libs/$CONFIG"
-  export GRPC_PYTHON_BUILD_WITH_CYTHON=1
-  export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
-  python $GRPCIO/setup.py gather --test --install
-  python $GRPCIO/setup.py build_ext --inplace
-  python $GRPCIO/setup.py build_py
-}
-
-make_virtualenv $1
+export LD_LIBRARY_PATH=$ROOT/libs/$CONFIG
+export DYLD_LIBRARY_PATH=$ROOT/libs/$CONFIG
+export PATH=$ROOT/bins/$CONFIG:$ROOT/bins/$CONFIG/protobuf:$PATH
+export CFLAGS="-I$ROOT/include -std=c89"
+export LDFLAGS="-L$ROOT/libs/$CONFIG"
+export GRPC_PYTHON_BUILD_WITH_CYTHON=1
+export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
+
+cd $GRPCIO
+tox --notest
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index 9bdfbfc60c08defabe6424d12cdd17a584ace0e6..cc44a433bb181903e1ea1982723de15555d4d582 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -43,22 +43,6 @@ export LDFLAGS="-L$ROOT/libs/$CONFIG"
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
 export GRPC_PYTHON_ENABLE_CYTHON_TRACING=1
 
-VIRTUALENV=python"$PYVER"_virtual_environment
-source $VIRTUALENV/bin/activate
-
-(rm $GRPCIO/.coverage)   || true
-(rm $GRPCIO/.coverage.*) || true
-
-if python -u $GRPCIO/setup.py test; then
-  EXIT_CODE=0
-else
-  EXIT_CODE=$?
-fi
-
-cp $GRPCIO/report.xml $ROOT
-
 cd $GRPCIO
-(coverage combine) || true
-(coverage report --include='grpc/*' --omit='grpc/framework/alpha/*','grpc/early_adopter/*','grpc/framework/base/*''grpc/framework/face/*') || true
+tox
 
-exit $EXIT_CODE