diff --git a/.gitignore b/.gitignore
index 874bacdb3..ca75bddd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,5 +13,5 @@ build/
 doc/build/
 doc/source/api/
 dist/
-.testrepository/
+.stestr/
 releasenotes/build
diff --git a/.stestr.conf b/.stestr.conf
new file mode 100644
index 000000000..b0e6e1ada
--- /dev/null
+++ b/.stestr.conf
@@ -0,0 +1,3 @@
+[DEFAULT]
+test_path=./oslo_messaging/tests
+top_path=./
diff --git a/.testr.conf b/.testr.conf
deleted file mode 100644
index 6b66beff6..000000000
--- a/.testr.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-[DEFAULT]
-test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
-test_id_option=--load-list $IDFILE
-test_list_option=--list
-group_regex=${OS_GROUP_REGEX}
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 25e930e43..3b0880237 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -83,9 +83,9 @@ snowballstemmer==1.2.1
 Sphinx==1.6.2
 sphinxcontrib-websupport==1.0.1
 statsd==3.2.1
+stestr==2.0.0
 stevedore==1.20.0
 tenacity==4.4.0
-testrepository==0.0.18
 testscenarios==0.4
 testtools==2.2.0
 traceback2==1.4.0
diff --git a/test-requirements.txt b/test-requirements.txt
index 0ca12322c..826723bd6 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -7,14 +7,13 @@ hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
 
 fixtures>=3.0.0 # Apache-2.0/BSD
 mock>=2.0.0 # BSD
-python-subunit>=1.0.0 # Apache-2.0/BSD
-testrepository>=0.0.18 # Apache-2.0/BSD
 testscenarios>=0.4 # Apache-2.0/BSD
 testtools>=2.2.0 # MIT
 oslotest>=3.2.0 # Apache-2.0
 pifpaf>=0.10.0 # Apache-2.0
 # for test_matchmaker_redis
 redis>=2.10.0 # MIT
+stestr>=2.0.0 # Apache-2.0
 
 # for test_impl_zmq
 pyzmq>=14.3.1 # LGPL+BSD
diff --git a/tox.ini b/tox.ini
index c6ce87aa0..b7b75101d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,7 +13,7 @@ deps =
   -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
   -r{toxinidir}/test-requirements.txt
   -r{toxinidir}/requirements.txt
-commands = python setup.py testr --slowest --testr-args='{posargs}'
+commands = stestr run --slowest {posargs}
 
 [testenv:pep8]
 basepython = python3
@@ -39,14 +39,14 @@ basepython = python2.7
 setenv =
     {[testenv]setenv}
     TRANSPORT_DRIVER=rabbit
-commands = pifpaf run rabbitmq --  python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = pifpaf run rabbitmq --  stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py35-func-rabbit]
 basepython = python3.5
 setenv =
     {[testenv]setenv}
     TRANSPORT_DRIVER=rabbit
-commands = pifpaf run rabbitmq --  python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = pifpaf run rabbitmq --  stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-kafka]
 basepython = python2.7
@@ -54,7 +54,7 @@ setenv =
     {[testenv]setenv}
     TRANSPORT_URL=kafka://127.0.0.1:9092/
     OS_GROUP_REGEX=oslo_messaging.tests.functional
-commands = {toxinidir}/setup-test-env-kafka.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-kafka.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-amqp1]
 basepython = python2.7
@@ -64,7 +64,7 @@ setenv =
     AMQP1_BACKEND=qpidd
     ENVNAME={envname}
     WORKDIR={toxworkdir}
-commands = {toxinidir}/tools/setup-test-env-amqp1.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/tools/setup-test-env-amqp1.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py35-func-amqp1]
 basepython = python3.5
@@ -74,7 +74,7 @@ setenv =
     AMQP1_BACKEND=qpidd
     ENVNAME={envname}
     WORKDIR={toxworkdir}
-commands = {toxinidir}/tools/setup-test-env-amqp1.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/tools/setup-test-env-amqp1.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py35-func-kafka]
 basepython = python3.5
@@ -82,27 +82,27 @@ setenv =
     {[testenv]setenv}
     TRANSPORT_URL=kafka://127.0.0.1:9092/
     OS_GROUP_REGEX=oslo_messaging.tests.functional
-commands = {toxinidir}/setup-test-env-kafka.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-kafka.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-zmq]
 basepython = python2.7
-commands = {toxinidir}/setup-test-env-zmq.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-zmq.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py35-func-zmq]
 basepython = python3.5
-commands = {toxinidir}/setup-test-env-zmq.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-zmq.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-zmq-dyn]
 basepython = python2.7
-commands = {toxinidir}/setup-test-env-zmq-direct-dynamic.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-zmq-direct-dynamic.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-zmq-proxy]
 basepython = python2.7
-commands = {toxinidir}/setup-test-env-zmq-proxy.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-zmq-proxy.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:py27-func-zmq-pubsub]
 basepython = python2.7
-commands = {toxinidir}/setup-test-env-zmq-pub-sub.sh python setup.py testr --slowest --testr-args='{posargs:oslo_messaging.tests.functional}'
+commands = {toxinidir}/setup-test-env-zmq-pub-sub.sh stestr run --slowest {posargs:oslo_messaging.tests.functional}
 
 [testenv:bandit]
 basepython = python3