diff --git a/Attribute_wrapper/__init__.py b/Attribute_wrapper/__init__.py
index a917d916747f8d6a1c191e57c15ffd953486b29a..2787b160cc4c457efb5bd2fd32a15dbf21c7bd7c 100644
--- a/Attribute_wrapper/__init__.py
+++ b/Attribute_wrapper/__init__.py
@@ -5,4 +5,4 @@ try:
 except ImportError:  # for Python<3.8
     import importlib_metadata as metadata
 
-__version__ = metadata.version("AttributeWrapper")
+#__version__ = metadata.version("AttributeWrapper")
diff --git a/Attribute_wrapper/attribute_wrapper.py b/Attribute_wrapper/attribute_wrapper.py
index 4923c17127a80407c448092badf731dfe919350d..cbb0138a9eca149e9d2d955569d1a82636420b44 100644
--- a/Attribute_wrapper/attribute_wrapper.py
+++ b/Attribute_wrapper/attribute_wrapper.py
@@ -4,6 +4,7 @@
 import logging
 from functools import reduce
 from operator import mul
+from functools import wraps
 
 import numpy
 from tango import AttrWriteType, AttReqType
@@ -13,6 +14,7 @@ logger = logging.getLogger()
 
 __all__ = ["AttributeWrapper"]
 
+
 def fault_on_error():
     """
     Wrapper to catch exceptions. Sets the device in a FAULT state if any occurs.
@@ -63,7 +65,8 @@ class AttributeIO(object):
     def cached_write_function(self, value):
         """Writes the given value to the device, and updates the cache."""
 
-        # flexible array sizes are not supported by all clients. make sure we only write arrays of maximum size.
+        # flexible array sizes are not supported by all clients. make sure we only
+        # write arrays of maximum size.
         if self.attribute_wrapper.shape != ():
             if isinstance(value, numpy.ndarray):
                 value_shape = value.shape
@@ -117,14 +120,19 @@ class AttributeWrapper(attribute):
                 f"Attribute needs to be a Tango-supported numpy, str or bool type, but has type {datatype}"
             )
 
-        self.comms_id = comms_id  # store data that can be used to identify the comms interface to use. not used by the wrapper itself
-        self.comms_annotation = comms_annotation  # store data that can be used by the comms interface. not used by the wrapper itself
+        # store data that can be used to identify the comms interface to use. not
+        # used by the wrapper itself
+        self.comms_id = comms_id
+        # store data that can be used by the comms interface. not used by the
+        # wrapper itself
+        self.comms_annotation = comms_annotation
 
         self.datatype = datatype
 
         if dims == (1,):
             # scalar
-            # Tango defines a scalar as having dimensions (1,0), see https://pytango.readthedocs.io/en/stable/server_api/attribute.html
+            # Tango defines a scalar as having dimensions (1,0), see
+            # https://pytango.readthedocs.io/en/stable/server_api/attribute.html
             max_dim_x = 1
             max_dim_y = 0
             dtype = datatype
@@ -181,7 +189,8 @@ class AttributeWrapper(attribute):
                 read_func_wrapper reads the attribute value, stores it and returns it"
                 """
 
-                # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read.
+                # lofar.read_attribute ignores fisallowed. So check again if we're
+                # allowed to read.
                 if not device.is_attribute_access_allowed(AttReqType.READ_REQ):
                     return None
 
@@ -205,7 +214,8 @@ class AttributeWrapper(attribute):
                 read_func_wrapper reads the attribute value, stores it and returns it"
                 """
 
-                # lofar.read_attribute ignores fisallowed. So check again if we're allowed to read.
+                # lofar.read_attribute ignores fisallowed. So check again if we're
+                # allowed to read.
                 if not device.is_attribute_access_allowed(AttReqType.READ_REQ):
                     return None
 
@@ -225,7 +235,8 @@ class AttributeWrapper(attribute):
         # The provided function will be used with the call signature "(device: Device, req_type: AttReqType) -> bool".
         #
         # NOTE: fisallowed=<callable> does not work: https://gitlab.com/tango-controls/pytango/-/issues/435
-        # So we have to use fisallowed=<str> here, which causes the function device.<str> to be called.
+        # So we have to use fisallowed=<str> here, which causes the function
+        # device.<str> to be called.
         super().__init__(
             dtype=dtype,
             max_dim_y=max_dim_y,
diff --git a/Attribute_wrapper/cool_module.py b/Attribute_wrapper/cool_module.py
deleted file mode 100644
index bd9416c291b7ed52a278bc6966f2dac155e4aa05..0000000000000000000000000000000000000000
--- a/Attribute_wrapper/cool_module.py
+++ /dev/null
@@ -1,6 +0,0 @@
-""" Cool module containing functions, classes and other useful things """
-
-
-def greeter():
-    """Prints a nice message"""
-    print("Hello World!")
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..49d59571fbf6e077eece30f8c418b6aad15e20b0
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.1
diff --git a/requirements.txt b/requirements.txt
index 87f08311d942584129c1ccd977b00ca3d357a2b5..ad16c920e10a99e58dc092cad31462d0daa29c4d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,4 @@
 numpy >= 1.20.0 # BSD
-testtools>=2.2.0 # MIT
\ No newline at end of file
+stestr>=3.0.0 # Apache-2.0
+testscenarios>=0.5.0 # Apache-2.0/BSD
+testtools>=2.4.0 # MIT
\ No newline at end of file
diff --git a/tests/test_attr_wrapper.py b/tests/test_attr_wrapper.py
index 24d798869beac09d6c26f5618021702ec0430000..97985b1a55c93b191ecf14d170043ded9b71c661 100644
--- a/tests/test_attr_wrapper.py
+++ b/tests/test_attr_wrapper.py
@@ -6,7 +6,7 @@
 
 import asyncio
 
-import mock
+from unittest import mock
 import numpy
 
 # External imports
@@ -15,11 +15,10 @@ from tango.server import attribute, command, Device, DeviceMeta
 
 # Test imports
 from tango.test_context import DeviceTestContext
-import AttributeWrapper
-from tangostationcontrol.test import base
+from Attribute_wrapper.attribute_wrapper import AttributeWrapper
 
 # Internal imports
-from test.test_client import TestClient
+from test_client import TestClient
 
 SCALAR_DIMS = (1,)
 SPECTRUM_DIMS = (4,)
@@ -37,11 +36,12 @@ def dev_init(device):
         asyncio.run(i.async_set_comm_client(device, device.test_client))
     device.test_client.start()
 
+
 class device_wrapper(Device, metaclass=DeviceMeta):
     @classmethod
     def attr_list(cls):
         """Return a list of all the AttributeWrapper members of this class."""
-        return [v for k, v in cls.__dict__.items() if type(v) == AttributeWrapper]
+        return [v for k, v in cls.__dict__.items() if isinstance(v, AttributeWrapper)]
 
     def off(self):
         self.set_state(DevState.OFF)
@@ -52,12 +52,11 @@ class device_wrapper(Device, metaclass=DeviceMeta):
     def initialise(self):
         self.set_state(DevState.INIT)
 
-class TestAttributeTypes(base.TestCase):
+
+class TestAttributeTypes():
     def setUp(self):
         # Avoid the device trying to access itself as a client
-        self.deviceproxy_patch = mock.patch.object(
-            Device, "DeviceProxy"
-        )
+        self.deviceproxy_patch = mock.patch.object(device_wrapper, "DeviceProxy")
         self.deviceproxy_patch.start()
         self.addCleanup(self.deviceproxy_patch.stop)
 
@@ -572,7 +571,6 @@ class TestAttributeTypes(base.TestCase):
     def read_R_test(self, dev, dtype, test_type):
         """Test device"""
         with DeviceTestContext(dev, process=True) as proxy:
-
             # initialise
             proxy.initialise()
             proxy.on()
@@ -589,7 +587,8 @@ class TestAttributeTypes(base.TestCase):
                     proxy.image_R
                 )  # is needed for STR since they act differently
 
-                # cant use all() for 2d arrays so instead compare the dimensions and then flatten to 2d
+                # cant use all() for 2d arrays so instead compare the dimensions and
+                # then flatten to 2d
                 self.assertEqual(
                     val.shape,
                     expected.shape,
@@ -632,13 +631,11 @@ class TestAttributeTypes(base.TestCase):
     def write_RW_test(self, dev, dtype, test_type):
         """Test device"""
         with DeviceTestContext(dev, process=True) as proxy:
-
             # initialise
             proxy.initialise()
             proxy.on()
 
             if test_type == "scalar":
-
                 if dtype is str:
                     val = STR_SCALAR_VAL
                 else:
@@ -678,7 +675,6 @@ class TestAttributeTypes(base.TestCase):
 
         try:
             with DeviceTestContext(dev, process=True) as proxy:
-
                 # initialise
                 proxy.initialise()
                 proxy.on()
@@ -695,7 +691,8 @@ class TestAttributeTypes(base.TestCase):
                         proxy.image_RW
                     )  # is needed for STR since they act differently
 
-                    # cant use all() for 2d arrays so instead compare the dimensions and then flatten to 2d
+                    # cant use all() for 2d arrays so instead compare the dimensions and
+                    # then flatten to 2d
                     self.assertEqual(
                         val.shape,
                         expected.shape,
@@ -792,7 +789,6 @@ class TestAttributeTypes(base.TestCase):
         """Test device"""
         try:
             with DeviceTestContext(dev, process=True) as proxy:
-
                 # initialise
                 proxy.initialise()
                 proxy.on()
@@ -1029,12 +1025,10 @@ class TestAttributeTypes(base.TestCase):
             )
 
 
-class TestAttributeAccess(base.TestCase):
+class TestAttributeAccess():
     def setUp(self):
         # Avoid the device trying to access itself as a client
-        self.deviceproxy_patch = mock.patch.object(
-            Device, "DeviceProxy"
-        )
+        self.deviceproxy_patch = mock.patch.object(Device, "DeviceProxy")
         self.deviceproxy_patch.start()
         self.addCleanup(self.deviceproxy_patch.stop)
 
diff --git a/tests/test_client.py b/tests/test_client.py
index 1b31de2c47c7ec2255d98cbaa8e3c40e82af47ee..b1a0c98591294b4b6b13c7da0531cc455436d64e 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -6,13 +6,10 @@ import logging
 # External imports
 import numpy
 
-# Test imports
-from tangostationcontrol.clients.comms_client import CommClient
-
 logger = logging.getLogger()
 
 
-class TestClient(CommClient):
+class TestClient:
     """
     this class provides an example implementation of a comms_client.
     During initialisation it creates a correctly shaped zero filled value. on read that value is returned and on write its modified.
@@ -126,7 +123,8 @@ class TestClient(CommClient):
         # process the comms_annotation
         self._setup_annotation(annotation)
 
-        # get all the necessary data to set up the read/write functions from the AttributeWrapper
+        # get all the necessary data to set up the read/write functions from the
+        # AttributeWrapper
         dims, dtype = self._setup_value_conversion(attribute)
 
         # configure and return the read/write functions
diff --git a/tox.ini b/tox.ini
index d5388949afbca56f8f7bd3c979409c7cfd78d3b0..10e61a9c74aca3448266f66147ef9fe2c50ef057 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,6 +14,9 @@ setenv =
 deps =
     -r{toxinidir}/requirements.txt
     -r{toxinidir}/tests/requirements.txt
+commands_pre =
+    {envpython} --version
+    pip install --no-cache pytango
 commands =
     {envpython} --version
     {envpython} -m pytest
@@ -34,9 +37,9 @@ commands =
     black: {envpython} -m black --version
     black: {envpython} -m black --check --diff .
     pylint: {envpython} -m pylint --version
-    pylint: {envpython} -m pylint my_awesome_app tests
-    format: {envpython} -m autopep8 -v -aa --in-place --recursive my_awesome_app
-    format: {envpython} -m autopep8 -v -aa --in-place --recursive tests
+    pylint: {envpython} -m pylint AttributeWrapper tests
+    format: {envpython} -m autopep8 -v -aa --in-place --recursive Attribute_wrapper/
+    format: {envpython} -m autopep8 -v -aa --in-place --recursive tests/
     format: {envpython} -m black -v .