diff --git a/test/AllTypesFESA/README.md b/test/AllTypesFESA/README.md
index 49d00c5f94694b61b16adcd0fba6645b66716ac6..8a0cea20c23bbeddc4cb2d70e4793b7e142ebd3e 100644
--- a/test/AllTypesFESA/README.md
+++ b/test/AllTypesFESA/README.md
@@ -1,4 +1,3 @@
 # Usage
 
-Before you compile and synchronize the class make sure to run `copyDesigns.sh` which will take the latest silecsdesign and fesa design files and copy them to this FESA class project. After that the procedure to work with the class is the same as always.
-
+The `design` and `silecsdesign` files are also used by the codegen tests and are symlinked from the `silecs-codegen` tests.
diff --git a/test/README.md b/test/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c53fd311b4b6710a4859a9a8d785621b72cd34ae
--- /dev/null
+++ b/test/README.md
@@ -0,0 +1,10 @@
+# Testing AllTypesFESA class on the test PLC
+
+- In order to run the block mode tests, the generated *-block.scl file needs to be uploaded to the PLC.
+- In order to run the device mode tests, the generated *-device.scl file needs to be uploaded to the PLC. For device-mode it seems to be required to modifiy the DB Numbers by hand, according to the [generated sdf file](./AllTypesFESA_DU/generated-silecs//controller/tsts7001-device.sdf).
+
+More info on how to upload *.scl files and to change the DB numbers can be found [here](https://www-acc.gsi.de/wiki/Frontend/Upload_Controller_Siemens).
+
+## How tests work
+
+You can run the [silecsTypesTester.sh](./silecsTypesTester.sh) script which will synchronize, build and release the class. Then it will ask to startup and configure the class and PLC in device mode. Upon confirmation it will use `cmwTester.py` to test over the FESA interface. Finally the last steps are repeated for block mode.
diff --git a/test/cmwTester.py b/test/cmwTester.py
new file mode 100755
index 0000000000000000000000000000000000000000..6cea3bd3ade99eeb586178909f6704faed487294
--- /dev/null
+++ b/test/cmwTester.py
@@ -0,0 +1,80 @@
+#!/common/usr/cscofe/bin/rdapython
+
+import cmwrda
+import random
+import time
+import argparse
+
+parser = argparse.ArgumentParser(description="Test AllTypesFESA class")
+parser.add_argument("--block-mode", action="store_false", dest="block_mode", help="Select block mode for testing. Device mode otherwise.")
+
+args = parser.parse_args()
+
+
+fecName = "AllTypesFESA_DU.vmla016"
+devModeDevice = "allTypesDevModeFesaDevice"
+blockModeDevice = "allTypesBlkModeFesaDevice"
+
+if args.block_mode:
+    device = devModeDevice
+else:
+    device = blockModeDevice
+
+rwBlockProp = cmwrda.Rda(device, "MyRWBlockProp", fecName)
+
+setData = cmwrda.Data()
+setData.add(cmwrda.ValueScalar('RW_enum_fesa', cmwrda.RdaType['INT'], random.randint(0, 3)))
+setData.add(cmwrda.ValueScalar('RW_dt_fesa', cmwrda.RdaType['DOUBLE'], random.randrange(1893457980, 1893457999)))
+setData.add(cmwrda.ValueScalar('RW_real_fesa', cmwrda.RdaType['FLOAT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_dint_fesa', cmwrda.RdaType['INT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_int_fesa', cmwrda.RdaType['SHORT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_dword_fesa', cmwrda.RdaType['LONG'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_word_fesa', cmwrda.RdaType['INT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_byte_fesa', cmwrda.RdaType['SHORT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_char_fesa', cmwrda.RdaType['BYTE'], random.randrange(0, 100)))
+setData.add(cmwrda.ValueScalar('RW_date_fesa', cmwrda.RdaType['DOUBLE'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_string_fesa', cmwrda.RdaType['STRING'], "TestString"))
+setData.add(cmwrda.ValueScalar('RW_float32_fesa', cmwrda.RdaType['FLOAT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_uint32_fesa', cmwrda.RdaType['LONG'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_int32_fesa', cmwrda.RdaType['INT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_uint16_fesa', cmwrda.RdaType['INT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_int16_fesa', cmwrda.RdaType['SHORT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_uint8_fesa', cmwrda.RdaType['SHORT'], random.randrange(0, 10000)))
+setData.add(cmwrda.ValueScalar('RW_int8', cmwrda.RdaType['BYTE'], random.randrange(0, 100)))
+setData.add(cmwrda.ValueArray2D('RW2_dt_fesa', cmwrda.RdaType['DOUBLE_ARRAY_2D'], random.sample(range(1893457980, 1893457999), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_real_fesa', cmwrda.RdaType['FLOAT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_dint_fesa', cmwrda.RdaType['INT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_int_fesa', cmwrda.RdaType['SHORT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_dword_fesa', cmwrda.RdaType['LONG_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_word_fesa', cmwrda.RdaType['INT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_byte_fesa', cmwrda.RdaType['SHORT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_char_fesa', cmwrda.RdaType['BYTE_ARRAY_2D'], random.sample(range(0, 100), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_date_fesa', cmwrda.RdaType['DOUBLE_ARRAY_2D'], random.sample(range(1893457980, 1893457999), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_float32_fesa', cmwrda.RdaType['FLOAT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_uint32_fesa', cmwrda.RdaType['LONG_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_int32_fesa', cmwrda.RdaType['INT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_uint16_fesa', cmwrda.RdaType['INT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_int16_fesa', cmwrda.RdaType['SHORT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_uint8_fesa', cmwrda.RdaType['SHORT_ARRAY_2D'], random.sample(range(0, 10000), 4), 2, 2))
+setData.add(cmwrda.ValueArray2D('RW2_int8', cmwrda.RdaType['BYTE_ARRAY_2D'], random.sample(range(0, 100), 4), 2, 2))
+
+rwBlockProp.write(setData)
+
+time.sleep(0.5)
+
+readData = rwBlockProp.read()
+
+readValuesDict = readData.getValues()
+setValuesDict = setData.getValues()
+
+allEqual = True
+
+for key in readValuesDict:
+    readValue = readValuesDict[key]
+    setValue = setValuesDict[key]
+    if readValue.data() != setValue.data():
+        print("Mismatch between set value\n", setValue, "\nand read value\n", readValue)
+        allEqual = False
+
+if not allEqual:
+    exit(1)
\ No newline at end of file
diff --git a/test/silecsTypesTester.sh b/test/silecsTypesTester.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ecb6cc1529e0b995583469d5f73e4d564ecdf3bb
--- /dev/null
+++ b/test/silecsTypesTester.sh
@@ -0,0 +1,23 @@
+#/bin/sh
+
+set -e
+
+SCRIPT_PATH=$(dirname $(readlink -f "$0"))
+
+. $SCRIPT_PATH/../build/latest/silecs_environment
+
+RELATIVE_PATH=$(dirname "$0")
+
+yocto-fesa3 -c $RELATIVE_PATH/AllTypesFESA gen
+yocto-fesa3 -c $RELATIVE_PATH/AllTypesFESA build
+yocto-fesa3 -d $RELATIVE_PATH/AllTypesFESA_DU release -f vmla016
+
+silecs -r $SCRIPT_PATH/AllTypesFESA_DU -e int
+
+read -p "Load the device-mode scl on the PLC and startup the FESA class configure with device-mode device. Then press any key to continue"
+
+$SCRIPT_PATH/cmwTester.py --int
+
+read -p "Load the block-mode scl on the PLC and startup the FESA class configured with block-mode device. Then press any key to continue"
+
+$SCRIPT_PATH/cmwTester.py --int --block-mode