diff --git a/requirements-test.txt b/requirements-test.txt
deleted file mode 100644
index 63c3db3775f37647ff0ef7317a27e1a9e8976441..0000000000000000000000000000000000000000
--- a/requirements-test.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-pip
-setuptools
-wheel
-future==0.18.2
-ecdsa==0.16.1
-requests==2.27.1
-websocket-client==0.58.0
-pytz==2021.1
-pycryptodomex==3.10.1
-scrypt==0.8.18
-cryptography==3.4.7
-ruamel.yaml
-mock==4.0.3
-appdirs==1.4.4
-Click==7.1.2
-click_shell>=2.0
-prettytable
-pycodestyle==2.7.0
-pyflakes==2.3.1
-pylibscrypt==2.0.0
-six==1.15.0
-pytest
-pytest-mock
-pytest-cov
-coverage
-parameterized
-tox
-codacy-coverage
-virtualenv
-diff_match_patch
-asn1crypto
diff --git a/setup.py b/setup.py
index 70f87f0f06761e3730e25a236963c75929532a67..e8af9154616d1df7d8bc06f74c12d60fa7515017 100755
--- a/setup.py
+++ b/setup.py
@@ -18,22 +18,40 @@ except LookupError:
 
 VERSION = '0.26.0'
 
-tests_require = ['mock >= 2.0.0', 'pytest', 'pytest-mock', 'parameterized']
+tests_require = [
+    "mock == 4.0.3",
+    "pytest == 7.2.2",
+    "pytest-mock == 3.12.0",
+    "parameterized == 0.9.0",
+    "setuptools == 69.1.1",
+    "wheel == 0.42.0",
+    "future == 0.18.2",
+    "cryptography == 3.4.7",
+    "pycodestyle == 2.7.0",
+    "pyflakes == 2.3.1",
+    "pylibscrypt == 2.0.0",
+    "six == 1.15.0",
+    "pytest-cov == 4.1.0",
+    "coverage == 7.4.3",
+    "tox == 4.13.0",
+    "codacy-coverage == 1.3.11",
+    "virtualenv == 20.25.1",
+]
 
 requires = [
-    "ecdsa",
-    "requests",
-    "websocket-client",
-    "appdirs",
-    "scrypt",
-    "pycryptodomex",
-    "pytz",
-    "Click",
-    "click_shell",
-    "prettytable",
-    "ruamel.yaml",
-    "diff_match_patch",
-    "asn1crypto"
+    "ecdsa == 0.16.1",
+    "requests == 2.27.1",
+    "websocket-client == 0.58.0",
+    "appdirs == 1.4.4",
+    "scrypt == 0.8.18",
+    "pycryptodomex == 3.10.1",
+    "pytz == 2021.1",
+    "Click == 8.0.0",
+    "click_shell == 2.1",
+    "prettytable == 3.8.0",
+    "ruamel.yaml == 0.18.6",
+    "diff_match_patch == 20230430",
+    "asn1crypto == 1.5.1"
 ]
 
 
@@ -105,5 +123,6 @@ if __name__ == '__main__':
         },
         setup_requires=['pytest-runner'],
         tests_require=tests_require,
+        extras_require={"tests": tests_require},
         include_package_data=True,
     )
diff --git a/tox.ini b/tox.ini
index a94c545803e932274c57ae70f4df8ccafcb2e83d..ae004a0fa898f919e375dec508a583da9566eda4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -3,8 +3,7 @@ envlist = py{27,35,36,37,38,39}
 skip_missing_interpreters = true
 
 [testenv]
-deps =
-    -rrequirements-test.txt
+extras = tests
 commands =
     coverage run --parallel-mode -m pytest {posargs}
     coverage combine
@@ -28,8 +27,7 @@ commands =
     coverage xml
 
 [testenv:py36]
-deps =
-    -rrequirements-test.txt
+extras = tests
 commands =
     coverage run --parallel-mode -m pytest {posargs}
     coverage combine
@@ -120,20 +118,20 @@ basepython=
     python
 changedir=
     docs
-deps=-rdocs/requirements.txt
-     sphinx
+extras = tests
+deps=sphinx
      sphinx-click
 commands=
     sphinx-build -b html ./ ./html
 
 [testenv:upload_coverage]
-deps = 
+deps =
     coverage
     codacy-coverage
 passenv = CODACY_PROJECT_TOKEN
 commands =
     python-codacy-coverage -r coverage.xml
-    
+
 # Flake8 Configuration
 [flake8]
 # Ignore some flake8-docstrings errors