diff --git a/Core/Material/Materials.h b/Core/Material/Materials.h
index f2c88773264ef2e892b3e126979550042dc948e4..3d36c516e9832ad82577d459dc238b6cbe48452d 100644
--- a/Core/Material/Materials.h
+++ b/Core/Material/Materials.h
@@ -20,11 +20,8 @@
 
 namespace Materials {
 
-IMaterial *createInvertedMaterial(const IMaterial *material);
-
+IMaterial* createInvertedMaterial(const IMaterial *material);
 
 }
 
-
-
 #endif // MATERIALS_H
diff --git a/Tests/UnitTests/Core/0/Histogram1DTest.h b/Tests/UnitTests/Core/0/Histogram1DTest.h
index d036cab58405c8d5215c2cc614241e741ca240e4..61c4c0e45638330b8769c84900a39262c31eae2a 100644
--- a/Tests/UnitTests/Core/0/Histogram1DTest.h
+++ b/Tests/UnitTests/Core/0/Histogram1DTest.h
@@ -249,6 +249,4 @@ TEST_F(Histogram1DTest, Addition)
     }
 }
 
-
 #endif // HISTOGRAM1DTEST_H
-
diff --git a/Tests/UnitTests/Core/0/main.cpp b/Tests/UnitTests/Core/0/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/0/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/0/testlist.h b/Tests/UnitTests/Core/0/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7c9049c3ec1708441cca0ae1676f16067222667
--- /dev/null
+++ b/Tests/UnitTests/Core/0/testlist.h
@@ -0,0 +1,11 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "CustomBinAxisTest.h"
+#include "LabelMapTest.h"
+#include "Histogram1DTest.h"
+#include "VariableBinAxisTest.h"
+#include "Histogram2DTest.h"
+#include "KVectorTest.h"
+#include "ConstKBinAxisTest.h"
+#include "FixedBinAxisTest.h"
+#include "CVectorTest.h"
diff --git a/Tests/UnitTests/Core/1/main.cpp b/Tests/UnitTests/Core/1/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/1/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/1/testlist.h b/Tests/UnitTests/Core/1/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..9db6e8934ced5ff0f792b4eb0e82d818bf99dee4
--- /dev/null
+++ b/Tests/UnitTests/Core/1/testlist.h
@@ -0,0 +1,10 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "FormFactorBasicTest.h"
+#include "LayerTest.h"
+#include "MultiLayerTest.h"
+#include "ParticleCoreShellTest.h"
+#include "LayerRoughnessTest.h"
+#include "ParticleTest.h"
+#include "ParticleCompositionTest.h"
+#include "ParticleLayoutTest.h"
diff --git a/Tests/UnitTests/Core/2/ScalarSpecularInfoMapTest.h b/Tests/UnitTests/Core/2/ScalarSpecularInfoMapTest.h
index 639dda200db9872db927bd4caedcf2b0635417dd..68ea3d809426313fc9fa465fccac25ef219dbf1d 100644
--- a/Tests/UnitTests/Core/2/ScalarSpecularInfoMapTest.h
+++ b/Tests/UnitTests/Core/2/ScalarSpecularInfoMapTest.h
@@ -2,10 +2,11 @@
 #define SCALARSPECULARINFOMAPTEST_H
 
 #include "MultiLayer.h"
+#include "HomogeneousMaterial.h"
+#include "Layer.h"
 #include "Pi.h"
 #include "ScalarRTCoefficients.h"
 #include "ScalarSpecularInfoMap.h"
-#include "Layer.h"
 #include <memory>
 
 class ScalarSpecularInfoMapTest : public ::testing :: Test
diff --git a/Tests/UnitTests/Core/2/SpecularSimulationTest.h b/Tests/UnitTests/Core/2/SpecularSimulationTest.h
index 4fc91ac098a5e593dcfdc4dae7e025ded5618dce..ec32ff18457749978f4a8b147b5437a3f1d3d18d 100644
--- a/Tests/UnitTests/Core/2/SpecularSimulationTest.h
+++ b/Tests/UnitTests/Core/2/SpecularSimulationTest.h
@@ -6,7 +6,7 @@
 #include "ISampleBuilder.h"
 #include "Exceptions.h"
 #include "FixedBinAxis.h"
-#include "Pi.h"
+#include "Units.h"
 #include "Layer.h"
 #include <iostream>
 
@@ -41,7 +41,6 @@ SpecularSimulationTest::SpecularSimulationTest()
     multilayer.addLayer(layer2);
 }
 
-
 TEST_F(SpecularSimulationTest, InitialState)
 {
     SpecularSimulation sim;
diff --git a/Tests/UnitTests/Core/2/main.cpp b/Tests/UnitTests/Core/2/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/2/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/2/testlist.h b/Tests/UnitTests/Core/2/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb8c60288d5b9716a11adb9651908625668b7368
--- /dev/null
+++ b/Tests/UnitTests/Core/2/testlist.h
@@ -0,0 +1,8 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "ScalarSpecularInfoMapTest.h"
+#include "MatrixSpecularInfoMapTest.h"
+#include "ScalarRTCoefficientsTest.h"
+#include "MatrixRTCoefficientsTest.h"
+#include "SpecularSimulationTest.h"
+#include "SpecularMatrixTest.h"
diff --git a/Tests/UnitTests/Core/3/main.cpp b/Tests/UnitTests/Core/3/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/3/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/3/testlist.h b/Tests/UnitTests/Core/3/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6856492d5bb56c9c31677dbc44479ac7f1ce86d
--- /dev/null
+++ b/Tests/UnitTests/Core/3/testlist.h
@@ -0,0 +1,9 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "MaskTest.h"
+#include "DetectorMaskTest.h"
+#include "PolygonTest.h"
+#include "SpecialFunctionsTest.h"
+#include "RectangularDetectorTest.h"
+#include "PrecomputedTest.h"
+#include "DetectorTest.h"
diff --git a/Tests/UnitTests/Core/4/HomogeneousMaterialTest.h b/Tests/UnitTests/Core/4/HomogeneousMaterialTest.h
index 6aff9bb6d07dc772ece7559a05e019e31a10bd9e..50aa0b72f1385ce7ebbeb26fc5db66bc311301a7 100644
--- a/Tests/UnitTests/Core/4/HomogeneousMaterialTest.h
+++ b/Tests/UnitTests/Core/4/HomogeneousMaterialTest.h
@@ -2,6 +2,8 @@
 #define HOMOGENEOUSMATERIALTEST_H
 
 #include "HomogeneousMaterial.h"
+#include "Rotations.h"
+#include "Units.h"
 
 class HomogeneousMaterialTest : public ::testing :: Test
 {
@@ -32,7 +34,6 @@ TEST_F(HomogeneousMaterialTest, HomogeneousMaterialWithRefIndex)
     EXPECT_EQ(complex_t(0.0,0.0), matrix2(0,1));
     EXPECT_EQ(complex_t(0.0,0.0), matrix2(1,0));
     EXPECT_EQ(complex_t(-5.0,12.0), matrix2(1,1));
-
 }
 
 TEST_F(HomogeneousMaterialTest, HomogeneousMaterialWithRefIndexParam)
@@ -46,7 +47,6 @@ TEST_F(HomogeneousMaterialTest, HomogeneousMaterialWithRefIndexParam)
     EXPECT_EQ(complex_t(0.0,0.0), matrix(0,1));
     EXPECT_EQ(complex_t(0.0,0.0), matrix(1,0));
     EXPECT_EQ(complex_t(-3.0,-4.0), matrix(1,1));
-
 }
 
 TEST_F(HomogeneousMaterialTest, HomogeneousMaterialTransform)
@@ -85,7 +85,6 @@ TEST_F(HomogeneousMaterialTest, HomogeneousMaterialClone)
     EXPECT_EQ(complex_t(0.0,0.0), matrix(1,0));
     EXPECT_EQ(complex_t(-3.0,4.0), matrix(1,1));
 
-
     complex_t refIndex2 = complex_t(2.0, 3.0);
     clone->setRefractiveIndex(refIndex2);
     EXPECT_EQ(refIndex2, clone->getRefractiveIndex());
@@ -96,18 +95,14 @@ TEST_F(HomogeneousMaterialTest, HomogeneousMaterialClone)
     EXPECT_EQ(complex_t(0.0,0.0), matrix2(1,0));
     EXPECT_EQ(complex_t(-5.0,12.0), matrix2(1,1));
 
-
-
     RotationZ transform(45.*Units::degree);
     const IMaterial * tMaterial = clone->createTransformedMaterial(transform);
 
     EXPECT_EQ("Material1", tMaterial->getName());
     EXPECT_EQ(refIndex2, tMaterial->getRefractiveIndex());
 
-
     delete tMaterial;
     delete clone;
-
 }
 
 #endif // HOMOGENEOUSMATERIALTEST_H
diff --git a/Tests/UnitTests/Core/4/main.cpp b/Tests/UnitTests/Core/4/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/4/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/4/testlist.h b/Tests/UnitTests/Core/4/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8f78a7e83a59c51037b8f7a8468c7ae7ca7db39
--- /dev/null
+++ b/Tests/UnitTests/Core/4/testlist.h
@@ -0,0 +1,15 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "RelDiffTest.h"
+#include "DWBASimulationTest.h"
+#include "HomogeneousMaterialTest.h"
+#include "ThreadInfoTest.h"
+#include "InstrumentTest.h"
+#include "TRangeTest.h"
+#include "ChiSquaredModuleTest.h"
+#include "CumulativeValueTest.h"
+#include "BeamTest.h"
+#include "HomogeneousMagneticMaterialTest.h"
+#include "Shape2DTest.h"
+#include "GISASSimulationTest.h"
+#include "AttLimitsTest.h"
diff --git a/Tests/UnitTests/Core/5/ParameterDistributionTest.h b/Tests/UnitTests/Core/5/ParameterDistributionTest.h
index ae296a3c64753809f8bb46d3b3e5972edcd678d3..e5c6f3fa30bc1a8ae3876ccd181cf8e45e73a94d 100644
--- a/Tests/UnitTests/Core/5/ParameterDistributionTest.h
+++ b/Tests/UnitTests/Core/5/ParameterDistributionTest.h
@@ -3,6 +3,7 @@
 
 #include "ParameterDistribution.h"
 #include "Distributions.h"
+#include "Exceptions.h"
 #include "ParameterSample.h"
 #include "IParameterized.h"
 #include <cmath>
diff --git a/Tests/UnitTests/Core/5/main.cpp b/Tests/UnitTests/Core/5/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/5/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/5/testlist.h b/Tests/UnitTests/Core/5/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcbec717e96e2e7697b0b95ff5060ca42f39d437
--- /dev/null
+++ b/Tests/UnitTests/Core/5/testlist.h
@@ -0,0 +1,9 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "IParameterizedTest.h"
+#include "ParameterDistributionTest.h"
+#include "DistributionHandlerTest.h"
+#include "DistributionsTest.h"
+#include "FTDistributionsTest.h"
+#include "ParameterPoolTest.h"
+#include "RealParameterWrapperTest.h"
diff --git a/Tests/UnitTests/Core/6/main.cpp b/Tests/UnitTests/Core/6/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/6/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/6/testlist.h b/Tests/UnitTests/Core/6/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a4c2af12eb24c7c758a3d88c86a775dd42e0601
--- /dev/null
+++ b/Tests/UnitTests/Core/6/testlist.h
@@ -0,0 +1,6 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "IntensityDataFunctionsTest.h"
+#include "OutputDataTest.h"
+#include "OutputDataIteratorTest.h"
+#include "LLDataTest.h"
diff --git a/Tests/UnitTests/Core/CMakeLists.txt b/Tests/UnitTests/Core/CMakeLists.txt
index ad35e732d68646f88a129aa760f94a35efeaa373..553928177cb0a901357c1caa53d2add595215e40 100644
--- a/Tests/UnitTests/Core/CMakeLists.txt
+++ b/Tests/UnitTests/Core/CMakeLists.txt
@@ -2,7 +2,7 @@
 # CMakeLists.txt file for building and running unit tests
 ############################################################################
 
-include(GoogletestWrapper)
+include(AddGTest)
 
 # qtcreator prefers relative paths for project includes
 include_directories(
@@ -13,18 +13,19 @@ include_directories(
     ${GSL_INCLUDE_DIR}
     ${gtest_SOURCE_DIR}
     ${gtest_SOURCE_DIR}/include
- )
+    )
 if(BORNAGAIN_OPENMPI)
     include_directories(${MPI_INCLUDE_PATH})
 endif()
 
-WRAP_GTEST(TestCore0 "0/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore1 "1/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore2 "2/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore3 "3/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore4 "4/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore5 "5/*.h" ${BornAgainCore_LIBRARY} 0)
-WRAP_GTEST(TestCore6 "6/*.h" ${BornAgainCore_LIBRARY} 0)
+set(libs BornAgainCore)
 
-WRAP_GTEST(TestCoreFFspec Numeric/FormFactorSpecializationTest.h ${BornAgainCore_LIBRARY} 1)
-WRAP_GTEST(TestCoreFFsym  Numeric/FormFactorSymmetryTest.h       ${BornAgainCore_LIBRARY} 1)
+ADD_GTEST(Core "0"        ${libs} 0)
+ADD_GTEST(Core "1"        ${libs} 0)
+ADD_GTEST(Core "2"        ${libs} 0)
+ADD_GTEST(Core "3"        ${libs} 0)
+ADD_GTEST(Core "4"        ${libs} 0)
+ADD_GTEST(Core "5"        ${libs} 0)
+ADD_GTEST(Core "6"        ${libs} 0)
+ADD_GTEST(Core "Numeric0" ${libs} 1)
+ADD_GTEST(Core "Numeric1" ${libs} 1)
diff --git a/Tests/UnitTests/Core/LayerTest.h b/Tests/UnitTests/Core/LayerTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ed020ea3803102c73a79454467f7852b864b849
--- /dev/null
+++ b/Tests/UnitTests/Core/LayerTest.h
@@ -0,0 +1,86 @@
+#include "Layer.h"
+#include "HomogeneousMaterial.h"
+#include "Materials.h"
+#include "ParticleLayout.h"
+#include "Units.h"
+
+class LayerTest : public ::testing::Test
+{
+ protected:
+    LayerTest(){}
+    virtual ~LayerTest(){}
+};
+
+TEST_F(LayerTest, LayerInitialState)
+{
+    Layer layer;
+    EXPECT_EQ(nullptr, layer.getMaterial());
+    EXPECT_EQ(nullptr, layer.getLayout(0));
+    EXPECT_EQ(0, layer.getThickness());
+    EXPECT_FALSE(layer.hasDWBASimulation());
+    EXPECT_EQ(complex_t(1.0, 0.0), layer.getRefractiveIndex());
+    EXPECT_EQ(0.0, layer.getTotalParticleSurfaceDensity(0));
+    EXPECT_EQ("Layer", layer.getName());
+    EXPECT_EQ(nullptr, layer.createDWBASimulation());
+
+    Layer *new_layer = layer.clone();
+    EXPECT_EQ(nullptr, new_layer->getMaterial());
+    EXPECT_EQ(nullptr, new_layer->getLayout(0));
+    EXPECT_EQ(0, new_layer->getThickness());
+    EXPECT_FALSE(new_layer->hasDWBASimulation());
+    EXPECT_EQ(complex_t(1.0, 0.0), new_layer->getRefractiveIndex());
+    EXPECT_EQ(0.0, new_layer->getTotalParticleSurfaceDensity(0));
+    EXPECT_EQ("Layer", new_layer->getName());
+    EXPECT_EQ(nullptr, new_layer->createDWBASimulation());
+
+    delete new_layer;
+}
+
+TEST_F(LayerTest, LayerGetAndSet)
+{
+    HomogeneousMaterial air("air",0,0);
+    HomogeneousMaterial something("something",0,0.5);
+
+    Layer layer(air, 10*Units::nanometer);
+    EXPECT_EQ(air.getName(), layer.getMaterial()->getName());
+    EXPECT_EQ(nullptr, layer.getLayout(0));
+    EXPECT_EQ(10, layer.getThickness());
+    EXPECT_FALSE(layer.hasDWBASimulation());
+    EXPECT_EQ(complex_t(1,0), layer.getRefractiveIndex());
+    EXPECT_EQ(0.0, layer.getTotalParticleSurfaceDensity(0));
+    EXPECT_EQ("Layer", layer.getName());
+    EXPECT_EQ(nullptr, layer.createDWBASimulation());
+
+    layer.setThickness(20.0);
+    EXPECT_EQ(20, layer.getThickness());
+    layer.setMaterial(something);
+    EXPECT_EQ(something.getName(), layer.getMaterial()->getName());
+    EXPECT_EQ("Layer", layer.getName());
+    EXPECT_EQ(complex_t(1,0.5), layer.getRefractiveIndex());
+
+    Layer *new_layer = layer.clone();
+    EXPECT_EQ(something.getName(), new_layer->getMaterial()->getName());
+    EXPECT_EQ(nullptr, new_layer->getLayout(0));
+    EXPECT_EQ(20, new_layer->getThickness());
+    EXPECT_FALSE(new_layer->hasDWBASimulation());
+    EXPECT_EQ(complex_t(1,0.5), new_layer->getRefractiveIndex());
+    EXPECT_EQ(0.0, new_layer->getTotalParticleSurfaceDensity(0));
+    EXPECT_EQ("Layer", new_layer->getName());
+    EXPECT_EQ(nullptr, new_layer->createDWBASimulation());
+    delete new_layer;
+}
+
+TEST_F(LayerTest, LayerAndDecoration)
+{
+    HomogeneousMaterial air("air",0,0);
+    ParticleLayout *p_layout1 = new ParticleLayout();
+
+    Layer layer(air, 10*Units::nanometer);
+    layer.addLayout(*p_layout1);
+    //EXPECT_EQ(decoration1, layer.getLayout());
+    EXPECT_TRUE(layer.hasDWBASimulation());
+
+    ParticleLayout layout2;
+    layer.addLayout(layout2);
+    EXPECT_EQ("ParticleLayout", layer.getLayout(1)->getName());
+}
diff --git a/Tests/UnitTests/Core/Numeric/FormFactorSpecializationTest.h b/Tests/UnitTests/Core/Numeric0/FormFactorSpecializationTest.h
similarity index 100%
rename from Tests/UnitTests/Core/Numeric/FormFactorSpecializationTest.h
rename to Tests/UnitTests/Core/Numeric0/FormFactorSpecializationTest.h
diff --git a/Tests/UnitTests/Core/Numeric0/main.cpp b/Tests/UnitTests/Core/Numeric0/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/Numeric0/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/Numeric0/testlist.h b/Tests/UnitTests/Core/Numeric0/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..6afe17994500c147c393504aad7f593f58537e35
--- /dev/null
+++ b/Tests/UnitTests/Core/Numeric0/testlist.h
@@ -0,0 +1,3 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "FormFactorSpecializationTest.h"
diff --git a/Tests/UnitTests/Core/Numeric/FormFactorSymmetryTest.h b/Tests/UnitTests/Core/Numeric1/FormFactorSymmetryTest.h
similarity index 100%
rename from Tests/UnitTests/Core/Numeric/FormFactorSymmetryTest.h
rename to Tests/UnitTests/Core/Numeric1/FormFactorSymmetryTest.h
diff --git a/Tests/UnitTests/Core/Numeric1/main.cpp b/Tests/UnitTests/Core/Numeric1/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/Numeric1/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Core/Numeric1/testlist.h b/Tests/UnitTests/Core/Numeric1/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..52467146fc69017330a18593f2161fed8aac4566
--- /dev/null
+++ b/Tests/UnitTests/Core/Numeric1/testlist.h
@@ -0,0 +1,3 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "FormFactorSymmetryTest.h"
diff --git a/Tests/UnitTests/Core/main.cpp b/Tests/UnitTests/Core/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Core/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Fit/ConfigurableTest.h b/Tests/UnitTests/Fit/0/ConfigurableTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/ConfigurableTest.h
rename to Tests/UnitTests/Fit/0/ConfigurableTest.h
diff --git a/Tests/UnitTests/Fit/FitObjectTest.h b/Tests/UnitTests/Fit/0/FitObjectTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/FitObjectTest.h
rename to Tests/UnitTests/Fit/0/FitObjectTest.h
diff --git a/Tests/UnitTests/Fit/FitParameterLinkedTest.h b/Tests/UnitTests/Fit/0/FitParameterLinkedTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/FitParameterLinkedTest.h
rename to Tests/UnitTests/Fit/0/FitParameterLinkedTest.h
diff --git a/Tests/UnitTests/Fit/FitParameterTest.h b/Tests/UnitTests/Fit/0/FitParameterTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/FitParameterTest.h
rename to Tests/UnitTests/Fit/0/FitParameterTest.h
diff --git a/Tests/UnitTests/Fit/MinimizerOptionTest.h b/Tests/UnitTests/Fit/0/MinimizerOptionTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/MinimizerOptionTest.h
rename to Tests/UnitTests/Fit/0/MinimizerOptionTest.h
diff --git a/Tests/UnitTests/Fit/MinimizerOptionsTest.h b/Tests/UnitTests/Fit/0/MinimizerOptionsTest.h
similarity index 100%
rename from Tests/UnitTests/Fit/MinimizerOptionsTest.h
rename to Tests/UnitTests/Fit/0/MinimizerOptionsTest.h
diff --git a/Tests/UnitTests/Fit/0/main.cpp b/Tests/UnitTests/Fit/0/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..78ad33c8d727c8564b7f7e92d6e6ab41cdd5aa24
--- /dev/null
+++ b/Tests/UnitTests/Fit/0/main.cpp
@@ -0,0 +1,32 @@
+#ifdef _MSC_VER
+#define _VARIADIC_MAX 10
+#endif
+#include <gtest/gtest.h>
+
+#include "testlist.h"
+
+struct ErrorStreamRedirect {
+    ErrorStreamRedirect( std::streambuf* new_buffer )
+        : old( std::cerr.rdbuf(new_buffer) )
+    {}
+
+    ~ErrorStreamRedirect() {
+        std::cerr.rdbuf(old);
+    }
+
+private:
+    std::streambuf* old;
+};
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // redirect std::cerr stream
+    std::stringstream oss;
+    ErrorStreamRedirect redirecter( oss.rdbuf() );
+    (void)redirecter;
+
+    // run all google tests
+    return RUN_ALL_TESTS();
+}
diff --git a/Tests/UnitTests/Fit/0/testlist.h b/Tests/UnitTests/Fit/0/testlist.h
new file mode 100644
index 0000000000000000000000000000000000000000..77c50dcf4ae03846991e52d3bb37374963b5181c
--- /dev/null
+++ b/Tests/UnitTests/Fit/0/testlist.h
@@ -0,0 +1,8 @@
+// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
+
+#include "FitParameterTest.h"
+#include "FitParameterLinkedTest.h"
+#include "FitObjectTest.h"
+#include "MinimizerOptionsTest.h"
+#include "MinimizerOptionTest.h"
+#include "ConfigurableTest.h"
diff --git a/Tests/UnitTests/Fit/CMakeLists.txt b/Tests/UnitTests/Fit/CMakeLists.txt
index 356d5a8cd8d50a36bbd139c4af4f5f138ded5b75..8f883a2afb04e946004517984b0e9c52e2b4e1af 100644
--- a/Tests/UnitTests/Fit/CMakeLists.txt
+++ b/Tests/UnitTests/Fit/CMakeLists.txt
@@ -2,16 +2,18 @@
 # CMakeLists.txt file for building and running unit tests
 ############################################################################
 
+include(AddGTest)
+
 include_directories(
     ${BornAgainCore_INCLUDE_DIRS}
     ${BornAgainFit_INCLUDE_DIRS}
     ${EIGEN3_INCLUDE_DIR}
     ${RootMinimizers_INCLUDE_DIRS}
-)
-
+    ${gtest_SOURCE_DIR}
+    ${gtest_SOURCE_DIR}/include
+    )
 if(BORNAGAIN_OPENMPI)
     include_directories(${MPI_INCLUDE_PATH})
 endif()
 
-WRAP_GTEST(TestFit0 "*.h" ${BornAgainCore_LIBRARY} 0)
-
+ADD_GTEST(Fit "0" BornAgainCore 0)
diff --git a/Tests/UnitTests/GUI/CMakeLists.txt b/Tests/UnitTests/GUI/CMakeLists.txt
index 164ebc20537f73998c647458d082f55a1acc2ceb..88ef23219e8e30906f88d2ccb6ed56145c7d6850 100644
--- a/Tests/UnitTests/GUI/CMakeLists.txt
+++ b/Tests/UnitTests/GUI/CMakeLists.txt
@@ -25,9 +25,7 @@ set(CMAKE_AUTOMOC ON)
 
 add_executable(TestGUI ${source_files} ${include_files})
 
-target_link_libraries(TestGUI
-    ${BornAgainGUI_LIBRARY}
-)
+target_link_libraries(TestGUI ${BornAgainGUI_LIBRARY})
 
 qt5_use_modules(TestGUI Widgets Core Gui Designer PrintSupport Network Test)
 
diff --git a/cmake/bornagain/modules/GoogletestWrapper.cmake b/cmake/bornagain/modules/GoogletestWrapper.cmake
deleted file mode 100644
index 1c79b22e1f705ceab1fcfd35b7d75daa12e65176..0000000000000000000000000000000000000000
--- a/cmake/bornagain/modules/GoogletestWrapper.cmake
+++ /dev/null
@@ -1,60 +0,0 @@
-#################################################################################
-#
-#  BornAgain: simulate and fit scattering at grazing incidence
-#
-#  @file      cmake/bornagain/modules/GoogletestWrapper.cmake
-#  @brief     Implements function WRAP_GTEST(..)
-#
-#  @homepage  http://www.bornagainproject.org
-#  @license   GNU General Public License v3 or higher (see COPYING)
-#  @copyright Forschungszentrum Jülich GmbH 2016
-#  @authors   Scientific Computing Group at MLZ Garching
-#  @authors   J. Fisher, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
-#
-##################################################################################
-
-#  @brief Compile tests given as GLOBPATTERN, link with LINK_LIB, and execute
-
-#  STAGE=0: test run at compile time
-#  STAGE=1: test run upon "ctest"="make check"
-
-function(WRAP_GTEST TEST_NAME GLOBPATTERN LINK_LIBS STAGE)
-
-    file(GLOB INCLUDE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOBPATTERN})
-    list(SORT INCLUDE_FILES)
-
-    # Compose main program (C++ snippets plus #include's of our test code)
-    set(TMP "/* Generated by CMake. Do not edit. Do not put under version control. */\n")
-    file(READ "${TEMPLATE_DIR}/GoogletestHeader.cpp" TMPTMP)
-    set(TMP "${TMP}\n${TMPTMP}\n")
-    foreach(FILE ${INCLUDE_FILES})
-        set(TMP "${TMP}#include \"${CMAKE_CURRENT_SOURCE_DIR}/${FILE}\"\n")
-    endforeach()
-    file(READ "${TEMPLATE_DIR}/GoogletestFooter.cpp" TMPTMP)
-    set(TMP "${TMP}\n${TMPTMP}")
-
-    set(TEST_SRC "${BUILD_SRC_DIR}/${TEST_NAME}.cpp")
-    file(WRITE ${TEST_SRC} "${TMP}")
-
-    set(EXE ${TEST_NAME})
-    add_executable(${EXE} ${TEST_SRC})
-
-    target_link_libraries(${EXE} gtest ${LINK_LIBS})
-
-    # Build executable in lib directory,
-    # to prevent problems with finding libBornAgainCore.dll under Windows
-    # set_property(TARGET ${EXE} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
-
-    if    (${STAGE} EQUAL 0)
-        # Execute test just after compilation
-        add_custom_command(TARGET ${TEST_NAME} POST_BUILD COMMAND ${EXE})
-    elseif(${STAGE} EQUAL 1)
-        # Put test under control of CTest
-        add_test(${TEST_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${EXE})
-    else()
-        message(FATAL_ERROR "invalid parameter STAGE=${STAGE} in WRAP_GTEST")
-    endif()
-
-    # To make the .h files appear in QtCreator's project tree
-    add_custom_target("${TEST_NAME}_sources" SOURCES ${INCLUDE_FILES})
-endfunction()
diff --git a/cmake/generic/modules/AddGTest.cmake b/cmake/generic/modules/AddGTest.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1bae041e489bf09626aad03e8af4020cf6e5212d
--- /dev/null
+++ b/cmake/generic/modules/AddGTest.cmake
@@ -0,0 +1,36 @@
+#################################################################################
+#
+#  BornAgain: simulate and fit scattering at grazing incidence
+#
+#  @file      cmake/bornagain/modules/AddGTest.cmake
+#  @brief     Implements macro ADD_GTEST(..)
+#
+#  @homepage  http://www.bornagainproject.org
+#  @license   GNU General Public License v3 or higher (see COPYING)
+#  @copyright Forschungszentrum Jülich GmbH 2016
+#  @authors   Scientific Computing Group at MLZ Garching
+#  @authors   J. Fisher, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+#
+##################################################################################
+
+#  @brief Build test target from ${subdir}/main.cpp.
+
+#  stage=0: test run at compile time
+#  stage=1: test run upon "ctest"="make check"
+
+MACRO(ADD_GTEST project subdir libs stage)
+    set(TEST_NAME ${project}UnitTest${subdir})
+    set(EXE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
+    file(GLOB include_files ${subdir}/*.h)
+    add_executable(${TEST_NAME} ${subdir}/main.cpp ${include_files})
+    target_link_libraries(${TEST_NAME} gtest ${libs})
+    if    (${stage} EQUAL 0)
+        # Execute test just after compilation
+        add_custom_command(TARGET ${TEST_NAME} POST_BUILD COMMAND ${EXE})
+    elseif(${stage} EQUAL 1)
+        # Put test under control of CTest
+        add_test(${TEST_NAME} ${EXE})
+    else()
+        message(FATAL_ERROR "invalid parameter stage=${stage} in ADD_GTEST")
+    endif()
+ENDMACRO()
diff --git a/dev-tools/code-tools/update-gtestlist.py b/dev-tools/code-tools/update-gtestlist.py
new file mode 100755
index 0000000000000000000000000000000000000000..68e0e10b19e40ef4db5a25dd799f898835f303e4
--- /dev/null
+++ b/dev-tools/code-tools/update-gtestlist.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+"""
+Renews file testlist.h in given unit test subdirectory.
+This file just includes all other files from that directory.
+"""
+
+import fnmatch, glob, os, re, sys
+
+def find(pattern, path):
+    result = []
+    for root, dirs, files in os.walk(path):
+        for name in files:
+            if fnmatch.fnmatch(name, pattern):
+                result.append( name )
+    return result
+
+if( len(sys.argv)<=1 ):
+    print( "Usage: %s <directories>" % sys.argv[0] )
+    sys.exit(0)
+
+filelist = []
+for dir in sys.argv[1:]:
+    filelist = find( '*.h', dir )
+    fd = open( dir+"/testlist.h", "w" )
+    fd.write( "// To renew this file, run %s <directory>\n\n" % sys.argv[0] )
+    for fname in filelist:
+        if fname=="testlist.h":
+            continue
+        fd.write( '#include "%s"\n' % fname )
+    fd.close()