diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9ccf88d0be1327da755eb6ab5a6ea6dcb3b3e51e..e21a0ce8166960ab82cfa312a1cb6fc0d823fa3d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -60,9 +60,6 @@ build wheel for development: # Executed on non-tagged commit
 
 unit tests:
   stage: test
-  image: nexus.engageska-portugal.pt/ska-docker/tango-builder:latest
-  before_script:
-  - docker login -u $DOCKER_REGISTRY_USERNAME -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY_HOST
   tags:
     - docker-executor
   script:
@@ -76,9 +73,6 @@ unit tests:
 
 linting:
   stage: linting
-  image: nexus.engageska-portugal.pt/ska-docker/tango-builder:latest
-  before_script:
-  - docker login -u $DOCKER_REGISTRY_USERNAME -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY_HOST
   tags:
     - docker-executor
   script:
@@ -123,14 +117,12 @@ release docker image:
 
 pages:
   stage: pages
-  image: nexus.engageska-portugal.pt/ska-docker/tango-builder:latest
-  before_script:
-  - docker login -u $DOCKER_REGISTRY_USERNAME -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY_HOST
   tags:
     - docker-executor
   script:
     - cp -R build public
-    - mv public/lmcbaseclasses_htmlcov/* public
+    - mv public/htmlcov/* public
+
   artifacts:
     paths:
       - public
diff --git a/Makefile b/Makefile
index d9ee33f7b52237fd37fb995c845cd21692838f1f..9d111ec0cd7de5a588b8a09da922c53e163717d1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,14 @@
 #
 # Project makefile for a LMC Base Classes project. You should normally only need to modify
 # DOCKER_REGISTRY_USER and PROJECT below.
-#
-#
+
+# Use bash shell with pipefail option enabled so that the return status of a
+# piped command is the value of the last (rightmost) command to exit with a
+# non-zero status. This lets us pipe output into tee but still exit on test
+# failures.
+SHELL = /bin/bash
+.SHELLFLAGS = -o pipefail -c
+
 # DOCKER_REGISTRY_HOST, DOCKER_REGISTRY_USER and PROJECT are combined to define
 # the Docker tag for this project. The definition below inherits the standard
 # value for DOCKER_REGISTRY_HOST (=rnexus.engageska-portugal.pt) and overwrites
@@ -15,163 +21,31 @@ PROJECT = lmcbaseclasses
 #
 # include makefile to pick up the standard Make targets, e.g., 'make build'
 # build, 'make push' docker push procedure, etc. The other Make targets
-# ('make interactive', 'make test', etc.) are defined in this file.
+# ('make lint', 'make test', etc.) are defined in this file.
 #
 include .make/Makefile.mk
 
-#
-# IMAGE_TO_TEST defines the tag of the Docker image to test
-#
-IMAGE_TO_TEST = $(DOCKER_REGISTRY_HOST)/$(DOCKER_REGISTRY_USER)/$(PROJECT):latest
-
-#
-# CACHE_VOLUME is the name of the Docker volume used to cache eggs and wheels
-# used during the test procedure. The volume is not used during the build
-# procedure
-#
-# TODO: WORKS LOCALLY
-# CACHE_VOLUME = lmcbaseclasses-test-cache
-# TODO: WORKS CI/CD
-CACHE_VOLUME = $(PROJECT)-test-cache
-
-# optional docker run-time arguments
-DOCKER_RUN_ARGS =
-
-#
-# Never use the network=host mode when running CI jobs, and add extra
-# distinguishing identifiers to the network name and container names to
-# prevent collisions with jobs from the same project running at the same
-# time.
-#
-ifneq ($(CI_JOB_ID),)
-NETWORK_MODE := tangonet-$(CI_JOB_ID)
-CONTAINER_NAME_PREFIX := $(PROJECT)-$(CI_JOB_ID)-
-else
-CONTAINER_NAME_PREFIX := $(PROJECT)-
-endif
-
-ifeq ($(OS),Windows_NT)
-    $(error Sorry, Windows is not supported yet)
-else
-	UNAME_S := $(shell uname -s)
-	ifeq ($(UNAME_S),Linux)
-		DISPLAY ?= :0.0
-		NETWORK_MODE ?= host
-		XAUTHORITY_MOUNT := /tmp/.X11-unix:/tmp/.X11-unix
-		XAUTHORITY ?= /hosthome/.Xauthority
-		# /bin/sh (=dash) does not evaluate 'docker network' conditionals correctly
-		SHELL := /bin/bash
-	endif
-	ifeq ($(UNAME_S),Darwin)
-		IF_INTERFACE := $(shell netstat -nr -f inet | awk '{ if ($$1 ~/default/ && $$4 ~/en/) { print $$4} }')
-		DISPLAY := $(shell ifconfig $(IF_INTERFACE) | awk '{ if ($$1 ~/inet$$/) { print $$2} }'):0
-		# network_mode = host doesn't work on MacOS, so fix to the internal network
-		NETWORK_MODE := tangonet
-		XAUTHORITY_MOUNT := $(HOME):/hosthome:ro
-		XAUTHORITY := /hosthome/.Xauthority
-	endif
-endif
-
-#
-# When running in network=host mode, point devices at a port on the host
-# machine rather than at the container.
-#
-ifeq ($(NETWORK_MODE),host)
-TANGO_HOST := $(shell hostname):10000
-MYSQL_HOST := $(shell hostname):3306
-else
-# distinguish the bridge network from others by adding the project name
-NETWORK_MODE := $(NETWORK_MODE)-$(PROJECT)
-TANGO_HOST := $(CONTAINER_NAME_PREFIX)databaseds:10000
-MYSQL_HOST := $(CONTAINER_NAME_PREFIX)tangodb:3306
-endif
-
-
-DOCKER_COMPOSE_ARGS := DISPLAY=$(DISPLAY) XAUTHORITY=$(XAUTHORITY) TANGO_HOST=$(TANGO_HOST) \
-		NETWORK_MODE=$(NETWORK_MODE) XAUTHORITY_MOUNT=$(XAUTHORITY_MOUNT) MYSQL_HOST=$(MYSQL_HOST) \
-		DOCKER_REGISTRY_HOST=$(DOCKER_REGISTRY_HOST) DOCKER_REGISTRY_USER=$(DOCKER_REGISTRY_USER) \
-		CONTAINER_NAME_PREFIX=$(CONTAINER_NAME_PREFIX) COMPOSE_IGNORE_ORPHANS=true
-
-#
-# Defines a default make target so that help is printed if make is called
-# without a target
-#
 .DEFAULT_GOAL := help
 
-# TODO: WORKS LOCALLY
-# DOCKER_NETWORK := $(shell echo "$(notdir $(CURDIR))"_default | tr -d "-" | tr A-Z a-z)
-# TODO: WORKS CI/CD
-DOCKER_NETWORK := $(shell echo "$(notdir $(CURDIR))"_default | tr A-Z a-z)
+test: ## test lmcbaseclasses Python code
+	mkdir -p build
+	python3 setup.py test | tee build/setup_py_test.stdout
+	mv coverage.xml build
 
-#
-# defines a function to copy the ./test-harness directory into the container
-# and then runs the requested make target in the container. The container is:
-#
-#   1. attached to the network of the docker-compose test system
-#   2. uses a persistent volume to cache Python eggs and wheels so that fewer
-#      downloads are required
-#   3. uses a transient volume as a working directory, in which untarred files
-#      and test output can be written in the container and subsequently copied
-#      to the host
-#
-make = tar -c test-harness/ | \
-	   docker run -i --rm --network=$(NETWORK_MODE) \
-	   -e TANGO_HOST=$(TANGO_HOST) \
-	   -v $(CACHE_VOLUME):/home/tango/.cache \
-	   -v /build -w /build -u tango $(DOCKER_RUN_ARGS) $(IMAGE_TO_TEST) \
-	   bash -c "sudo chown -R tango:tango /build && \
-	   tar x --strip-components 1 --warning=all && \
-	   make TANGO_HOST=$(TANGO_HOST) $1"
-
-test: DOCKER_RUN_ARGS = --volumes-from=$(BUILD)
-test: build up ## test the application
-	$(INIT_CACHE)
-	$(call make,test); \
-	  status=$$?; \
-	  docker cp $(BUILD):/build .; \
-	  $(MAKE) down; \
-	  exit $$status
-
-lint: DOCKER_RUN_ARGS = --volumes-from=$(BUILD)
-lint: build up ## lint the application (static code analysis)
-	$(INIT_CACHE)
-	$(call make,lint); \
-	  status=$$?; \
-	  docker cp $(BUILD):/build .; \
-	  $(MAKE) down; \
-	  exit $$status
-
-pull:  ## download the application image
-	docker pull $(IMAGE_TO_TEST)
+lint: ## lint lmcbaseclasses Python code
+	python3 -m pip install -U pylint==2.4.4
+	python3 -m pip install pylint2junit
+	mkdir -p build/reports
+	pylint --output-format=parseable src/ska | tee build/code_analysis.stdout
+	pylint --output-format=pylint2junit.JunitReporter src/ska > build/reports/linting.xml
 
-up: build  ## start develop/test environment
-ifneq ($(NETWORK_MODE),host)
-	docker network inspect $(NETWORK_MODE) &> /dev/null || ([ $$? -ne 0 ] && docker network create $(NETWORK_MODE))
-endif
-	$(DOCKER_COMPOSE_ARGS) docker-compose up -d
+test-in-docker: build ## Build the docker image and run tests inside it.
+	@docker run $(IMAGE):$(VERSION) make test
 
-interactive: up
-interactive:  ## start an interactive session using the project image (caution: R/W mounts source directory to /app)
-	docker run --rm -it -p 3000:3000 --name=$(CONTAINER_NAME_PREFIX)dev -e TANGO_HOST=$(TANGO_HOST) --network=$(NETWORK_MODE) \
-          -v $(CURDIR):/app $(IMAGE_TO_TEST) /bin/bash
-
-down:  ## stop develop/test environment and any interactive session
-	docker ps | grep $(CONTAINER_NAME_PREFIX)dev && docker stop $(PROJECT)-dev || true
-	$(DOCKER_COMPOSE_ARGS) docker-compose down
-ifneq ($(NETWORK_MODE),host)
-	docker network inspect $(NETWORK_MODE) &> /dev/null && ([ $$? -eq 0 ] && docker network rm $(NETWORK_MODE)) || true
-endif
+lint-in-docker: build ## Build the docker image and run lint inside it.
+	@docker run $(IMAGE):$(VERSION) make lint
 
 help:  ## show this help.
 	@grep -hE '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
 
-.PHONY: all test up down help
-
-# Creates Docker volume for use as a cache, if it doesn't exist already
-INIT_CACHE = \
-	docker volume ls | grep $(CACHE_VOLUME) || \
-	docker create --name $(CACHE_VOLUME) -v $(CACHE_VOLUME):/cache $(IMAGE_TO_TEST)
-
-# http://cakoose.com/wiki/gnu_make_thunks
-BUILD_GEN = $(shell docker create -v /build $(IMAGE_TO_TEST))
-BUILD = $(eval BUILD := $(BUILD_GEN))$(BUILD)
+.PHONY: test lint test-in-docker lint-in-docker help
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 6858167c160f3bc607ab6b28b332a1e0676deb4e..0000000000000000000000000000000000000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# Docker compose file for LMC Base classes.
-# Contains services for TANGO database, database device server.
-#
-# Defines:
-#   - tangodb: MariaDB database with TANGO schema
-#   - databaseds: TANGO database device server
-#   - basedevice: Container having SKABaseDevice class
-#   - alarmhandler: Container having SKAAlarmHandler class
-#   - capability: Container having SKACapability class
-#   - logger: Container having SKALogger class
-#   - master: Container having SKAMaster class
-#   - obsdevice: Container having SKAObsDevice class
-#   - subarray: Container having SKASubarray class
-#   - telstate: Container having SKATelState class
-#   - logtest: Container having SKASubarray class for SKALogger testing
-#
-# Requires:
-#   - None
-#
-version: '2'
-volumes:
-  tangodb: {}
-
-services:
-  tangodb:
-    image: nexus.engageska-portugal.pt/ska-docker/tango-db:latest
-    restart: unless-stopped
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}tangodb
-    environment:
-      - MYSQL_ROOT_PASSWORD=secret
-      - MYSQL_DATABASE=tango
-      - MYSQL_USER=tango
-      - MYSQL_PASSWORD=tango
-    volumes:
-      - tangodb:/var/lib/mysql
-
-  databaseds:
-    image: nexus.engageska-portugal.pt/ska-docker/tango-cpp:latest
-    restart: unless-stopped
-    depends_on:
-      - tangodb
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}databaseds
-    environment:
-      - MYSQL_HOST=${MYSQL_HOST}
-      - MYSQL_DATABASE=tango
-      - MYSQL_USER=tango
-      - MYSQL_PASSWORD=tango
-      - TANGO_HOST=${TANGO_HOST}
-    entrypoint:
-      - /usr/local/bin/wait-for-it.sh
-      - ${MYSQL_HOST}
-      - --timeout=30
-      - --strict
-      - --
-      - /usr/local/bin/DataBaseds
-      - "2"
-      - -ORBendPoint
-      - giop:tcp::10000
-
-  basedevice:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}basedevice
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKABaseDevice/01 SKABaseDevice ska/basedevice/01 &&\
-             SKABaseDevice 01"
-
-  alarmhandler:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}alarmhandler
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKAAlarmHandler/01 SKAAlarmhandler ska/alarmhandler/01 &&\
-             SKAAlarmHandler 01"
-
-  capability:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}capability
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKACapability/01 SKACapability ska/capability/01 &&\
-             SKACapability 01"
-
-  logger:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}logger
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKALogger/01 SKALogger ska/logger/01 &&\
-             SKALogger 01"
-
-  master:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}master
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKAMaster/01 SKAMaster ska/master/01 &&\
-             SKAMaster 01"
-
-  obsdevice:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}obsdevice
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKAObsDevice/01 SKAObsDevice ska/obsdevice/01 &&\
-             SKAObsDevice 01"
-
-  subarray:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}subarray
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKASubarray/01 SKASubarray ska/subarray/01 &&\
-             SKASubarray 01"
-
-  telstate:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}telstate
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKATelState/01 SKATelState ska/telstate/01 &&\
-             SKATelState 01"
-
-  logtest:
-    image: ${DOCKER_REGISTRY_HOST}/${DOCKER_REGISTRY_USER}/lmcbaseclasses:latest
-    restart: unless-stopped
-    depends_on:
-      - databaseds
-    network_mode: ${NETWORK_MODE}
-    container_name: ${CONTAINER_NAME_PREFIX}testdevice
-    environment:
-      - TANGO_HOST=${TANGO_HOST}
-    command: >
-      sh -c "wait-for-it.sh ${TANGO_HOST} --timeout=30 --strict --
-             tango_admin --add-server SKASubarray/02 SKASubarray logger/test/1 &&\
-             SKASubarray 02"
diff --git a/setup.cfg b/setup.cfg
index b7420bf3b0879bdec0f0c66bff6966316bc211fd..f63a5c1986ad52f5101a36f7c51dfd01bdf3f2e6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,11 +10,11 @@ testpaths = tests
 addopts = --forked
           --verbose
           --json-report
-          --json-report-file=htmlcov/report.json
+          --json-report-file=build/htmlcov/report.json
           --cov-report term
           --cov-report html
           --cov-report xml
           --cov=ska.base
-          --junitxml=/build/reports/unit-tests.xml
+          --junitxml=build/reports/unit-tests.xml
 console_output_style = progress
 junit_family = legacy
diff --git a/test-harness/Makefile b/test-harness/Makefile
deleted file mode 100644
index 60fa18b75c85802c8c5ba4e56bfac78f0661aa50..0000000000000000000000000000000000000000
--- a/test-harness/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# Use bash shell with pipefail option enabled so that the return status of a
-# piped command is the value of the last (rightmost) commnand to exit with a
-# non-zero status. This lets us pipe output into tee but still exit on test
-# failures.
-SHELL = /bin/bash
-.SHELLFLAGS = -o pipefail -c
-
-all: test lint
-
-# wait for the device to be available before beginning the test
-# A temporary volume is mounted at /build when 'make test' is executing.
-# The following steps copy across useful output to this volume which can
-# then be extracted to form the CI summary for the test procedure.
-test:
-	retry --max=10 -- tango_admin --ping-device ska/basedevice/01
-	retry --max=10 -- tango_admin --ping-device ska/alarmhandler/01
-	retry --max=10 -- tango_admin --ping-device ska/capability/01
-	retry --max=10 -- tango_admin --ping-device ska/logger/01
-	retry --max=10 -- tango_admin --ping-device ska/master/01
-	retry --max=10 -- tango_admin --ping-device ska/obsdevice/01
-	retry --max=10 -- tango_admin --ping-device ska/subarray/01
-	retry --max=10 -- tango_admin --ping-device ska/telstate/01
-
-	cd /app && python setup.py test | tee setup_py_test.stdout && \
-	mkdir -p /build/reports && \
-	mv /app/setup_py_test.stdout /build/lmcbaseclasses_setup_py_test.stdout && \
-	mv /app/htmlcov /build/lmcbaseclasses_htmlcov && \
-	mv /app/coverage.xml /build/reports/code-coverage.xml
-
-# wait for the device to be available before beginning the test
-# A temporary volume is mounted at /build when 'make test' is executing.
-# The following steps copy across useful output to this volume which can
-# then be extracted to form the CI summary for the test procedure.
-# FIXME: Add pylint2junit to the tango-builder:latest image so that we don't need to install it here.
-# FIXME: Missing functionality in pylint2junit prevents converting from parseable to xml. Once it's implemented there is no need to run linting twice.
-lint:
-	python3 -m pip install -U pylint==2.4.4; \
-	python3 -m pip install pylint2junit; \
-	mkdir -p /build/reports; \
-	cd /app && pylint --output-format=parseable src/ska | tee /build/code_analysis.stdout; \
-	cd /app && pylint --output-format=pylint2junit.JunitReporter src/ska > /build/reports/linting.xml;
-
-.PHONY: all test lint
diff --git a/tests/test_logger_device.py b/tests/test_logger_device.py
index d60e5038851971a4dcb15fe717f70a7615284cf8..1bc03dbd9090febaf565710ec9bf8fda8bc74c3c 100644
--- a/tests/test_logger_device.py
+++ b/tests/test_logger_device.py
@@ -10,13 +10,22 @@
 
 import re
 import pytest
-from tango import DevState, DeviceProxy
+from tango import DevState
+from tango.test_context import MultiDeviceTestContext
+from ska.base.logger_device import SKALogger
+from ska.base.subarray_device import SKASubarray
 import tango
 
 # PROTECTED REGION ID(SKALogger.test_additional_imports) ENABLED START #
 from ska.base.control_model import (
-    AdminMode, ControlMode, HealthState, LoggingLevel, SimulationMode, TestMode
+    AdminMode,
+    ControlMode,
+    HealthState,
+    LoggingLevel,
+    SimulationMode,
+    TestMode,
 )
+
 # PROTECTED REGION END #    //  SKALogger.test_additional_imports
 
 
@@ -25,9 +34,11 @@ from ska.base.control_model import (
 # PROTECTED REGION END #    //  SKALogger.test_SKALogger_decorators
 class TestSKALogger(object):
     """Test case for packet generation."""
-    properties = {'SkaLevel': '1',
-                  'GroupDefinitions': '',
-                  }
+
+    properties = {
+        "SkaLevel": "1",
+        "GroupDefinitions": "",
+    }
 
     @classmethod
     def mocking(cls):
@@ -59,38 +70,15 @@ class TestSKALogger(object):
         assert tango_context.device.Status() == "The device is in OFF state."
         # PROTECTED REGION END #    //  SKALogger.test_Status
 
-    # PROTECTED REGION ID(SKALogger.test_SetLoggingLevel_decorators) ENABLED START #
-    @pytest.mark.parametrize("logging_level", [int(tango.LogLevel.LOG_ERROR)])
-    @pytest.mark.parametrize("logging_target", ["logger/test/1"])
-    # PROTECTED REGION END #    //  SKALogger.test_SetLoggingLevel_decorators
-    def test_SetLoggingLevel(self, tango_context,
-                             logging_level, logging_target):
-        """Test for SetLoggingLevel"""
-        # PROTECTED REGION ID(SKALogger.test_SetLoggingLevel) ENABLED START #
-        # initial setting must not be same as what it will be set to
-        dev_proxy = DeviceProxy(logging_target)
-        dev_proxy.loggingLevel = int(tango.LogLevel.LOG_FATAL)
-        assert dev_proxy.loggingLevel != logging_level
-
-        levels = []
-        levels.append(logging_level)
-        targets = []
-        targets.append(logging_target)
-        device_details = []
-        device_details.append(levels)
-        device_details.append(targets)
-        tango_context.device.SetLoggingLevel(device_details)
-        assert dev_proxy.loggingLevel == logging_level
-        # PROTECTED REGION END #    //  SKALogger.test_SetLoggingLevel
-
     # PROTECTED REGION ID(SKALogger.test_GetVersionInfo_decorators) ENABLED START #
     # PROTECTED REGION END #    //  SKALogger.test_GetVersionInfo_decorators
     def test_GetVersionInfo(self, tango_context):
         """Test for GetVersionInfo"""
         # PROTECTED REGION ID(SKALogger.test_GetVersionInfo) ENABLED START #
         versionPattern = re.compile(
-            r'SKALogger, lmcbaseclasses, [0-9].[0-9].[0-9], '
-            r'A set of generic base devices for SKA Telescope.')
+            r"SKALogger, lmcbaseclasses, [0-9].[0-9].[0-9], "
+            r"A set of generic base devices for SKA Telescope."
+        )
         versionInfo = tango_context.device.GetVersionInfo()
         assert (re.match(versionPattern, versionInfo[0])) is not None
         # PROTECTED REGION END #    //  SKALogger.test_GetVersionInfo
@@ -101,8 +89,9 @@ class TestSKALogger(object):
         """Test for buildState"""
         # PROTECTED REGION ID(SKALogger.test_buildState) ENABLED START #
         buildPattern = re.compile(
-            r'lmcbaseclasses, [0-9].[0-9].[0-9], '
-            r'A set of generic base devices for SKA Telescope')
+            r"lmcbaseclasses, [0-9].[0-9].[0-9], "
+            r"A set of generic base devices for SKA Telescope"
+        )
         assert (re.match(buildPattern, tango_context.device.buildState)) is not None
         # PROTECTED REGION END #    //  SKALogger.test_buildState
 
@@ -111,7 +100,7 @@ class TestSKALogger(object):
     def test_versionId(self, tango_context):
         """Test for versionId"""
         # PROTECTED REGION ID(SKALogger.test_versionId) ENABLED START #
-        versionIdPattern = re.compile(r'[0-9].[0-9].[0-9]')
+        versionIdPattern = re.compile(r"[0-9].[0-9].[0-9]")
         assert (re.match(versionIdPattern, tango_context.device.versionId)) is not None
         # PROTECTED REGION END #    //  SKALogger.test_versionId
 
@@ -162,3 +151,30 @@ class TestSKALogger(object):
         # PROTECTED REGION ID(SKALogger.test_testMode) ENABLED START #
         assert tango_context.device.testMode == TestMode.NONE
         # PROTECTED REGION END #    //  SKALogger.test_testMode
+
+
+def test_SetLoggingLevel():
+    """Test for SetLoggingLevel"""
+    logging_level = int(tango.LogLevel.LOG_ERROR)
+    logging_target = "logger/target/1"
+    logger_device = "logger/device/1"
+    devices_info = (
+        {"class": SKALogger, "devices": [{"name": logger_device}]},
+        {"class": SKASubarray, "devices": [{"name": logging_target}]},
+    )
+
+    with MultiDeviceTestContext(devices_info, process=False) as multi_context:
+        dev_proxy = multi_context.get_device(logging_target)
+        dev_proxy.Init()
+        dev_proxy.loggingLevel = int(tango.LogLevel.LOG_FATAL)
+        assert dev_proxy.loggingLevel != logging_level
+
+        levels = []
+        levels.append(logging_level)
+        targets = []
+        targets.append(multi_context.get_device_access(logging_target))
+        device_details = []
+        device_details.append(levels)
+        device_details.append(targets)
+        multi_context.get_device(logger_device).SetLoggingLevel(device_details)
+        assert dev_proxy.loggingLevel == logging_level