diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArray_write.cpp
index 73aa4fc6b251665d8c1f4f205a127c58755dc77f..d22438dda7dfe985b869d9abc8c9911efc186ad0 100644
--- a/examples/basics/joinedArray/joinedArray_write.cpp
+++ b/examples/basics/joinedArray/joinedArray_write.cpp
@@ -70,6 +70,8 @@ int main(int argc, char *argv[])
         // Get io settings from the config file or
         // create one with default settings here
         adios2::IO &io = adios.DeclareIO("Output");
+        // io.SetEngine("ADIOS1Writer");
+        // io.AddTransport("File", {{"library", "MPI"}});
 
         /*
          * Define joinable local array: type, name, global and local size
diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp
index 07759db41f82a76badab8a28635159d417befadf..713485cb904fe5920266488acc8e147123d4bdef 100644
--- a/source/adios2/core/VariableBase.cpp
+++ b/source/adios2/core/VariableBase.cpp
@@ -60,8 +60,7 @@ void VariableBase::SetSelection(const Dims start, const Dims count)
         }
 
         if (m_ShapeID == ShapeID::GlobalArray &&
-            (m_Shape.size() != m_Count.size() ||
-             m_Shape.size() != m_Start.size()))
+            (m_Shape.size() != count.size() || m_Shape.size() != start.size()))
         {
             throw std::invalid_argument("ERROR: count and start must be the "
                                         "same size as shape for variable " +
@@ -154,85 +153,133 @@ void VariableBase::ClearTransforms() noexcept { m_TransformsInfo.clear(); }
 // PRIVATE
 void VariableBase::InitShapeType()
 {
-    if (!m_Shape.empty() && m_Start.empty() && m_Count.empty())
+    if (!m_Shape.empty())
     {
-        if (m_DebugMode)
+        if (std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) == 1)
         {
-            if (m_ConstantDims)
+            if (!m_Start.empty() &&
+                std::count(m_Start.begin(), m_Start.end(), 0) != m_Start.size())
             {
-                throw std::invalid_argument(
-                    "ERROR: isConstantShape (true) argument is invalid "
-                    "with empty start and count "
-                    "arguments\n");
+                throw std::invalid_argument("ERROR: The Start array must be "
+                                            "empty or full-zero when defining "
+                                            "a Joined Array in call to "
+                                            "DefineVariable " +
+                                            m_Name + "\n");
             }
+            m_ShapeID = ShapeID::JoinedArray;
         }
-
-        m_ShapeID = ShapeID::GlobalArray;
-    }
-    else if (!m_Shape.empty() && m_Shape.size() == m_Start.size() &&
-             m_Shape.size() == m_Count.size())
-    {
-        if (m_DebugMode)
+        else if (std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) > 1)
         {
-            auto lf_LargerThanError = [&](const unsigned int i,
-                                          const std::string dims1,
-                                          const std::string dims2) {
-
-                const std::string iString(std::to_string(i));
-                throw std::invalid_argument(
-                    "ERROR: " + dims1 + "[" + iString + "] > " + dims2 + "[" +
-                    iString + "], in DefineVariable " + m_Name + "\n");
-            };
-
-            for (unsigned int i = 0; i < m_Shape.size(); ++i)
+            throw std::invalid_argument(
+                "ERROR: variable can't have more than one "
+                "JoinedDim in shape argument, in call to "
+                "DefineVariable " +
+                m_Name + "\n");
+        }
+        else if (m_Start.empty() && m_Count.empty())
+        {
+            if (m_Shape.size() == 1 && m_Shape.front() == LocalValueDim)
             {
-                if (m_Count[i] > m_Shape[i])
+                m_ShapeID = ShapeID::LocalValue;
+                m_SingleValue = true;
+            }
+            else
+            {
+                if (m_DebugMode)
                 {
-                    lf_LargerThanError(i, "count", "shape");
+                    if (m_ConstantDims)
+                    {
+                        throw std::invalid_argument(
+                            "ERROR: isConstantShape (true) argument is invalid "
+                            "with empty start and count "
+                            "arguments in call to "
+                            "DefineVariable " +
+                            m_Name + "\n");
+                    }
                 }
-                if (m_Start[i] > m_Shape[i])
+
+                m_ShapeID = ShapeID::GlobalArray;
+            }
+        }
+        else if (m_Shape.size() == m_Start.size() &&
+                 m_Shape.size() == m_Count.size())
+        {
+            if (m_DebugMode)
+            {
+                auto lf_LargerThanError = [&](const unsigned int i,
+                                              const std::string dims1,
+                                              const std::string dims2) {
+
+                    const std::string iString(std::to_string(i));
+                    throw std::invalid_argument(
+                        "ERROR: " + dims1 + "[" + iString + "] > " + dims2 +
+                        "[" + iString + "], in DefineVariable " + m_Name +
+                        "\n");
+                };
+
+                for (unsigned int i = 0; i < m_Shape.size(); ++i)
                 {
-                    lf_LargerThanError(i, "start", "shape");
+                    if (m_Count[i] > m_Shape[i])
+                    {
+                        lf_LargerThanError(i, "count", "shape");
+                    }
+                    if (m_Start[i] > m_Shape[i])
+                    {
+                        lf_LargerThanError(i, "start", "shape");
+                    }
                 }
             }
+            m_ShapeID = ShapeID::GlobalArray;
+        }
+        else
+        {
+            throw std::invalid_argument("ERROR: the "
+                                        "combination of shape, start and count "
+                                        "arguments is inconsistent, in call to "
+                                        "DefineVariable " +
+                                        m_Name + "\n");
         }
-
-        m_ShapeID = ShapeID::GlobalArray;
-    }
-    else if (m_Shape.empty() && m_Start.empty() && m_Count.empty())
-    {
-        m_ShapeID = ShapeID::GlobalValue;
-        m_SingleValue = true;
-    }
-    else if (m_Shape.empty() && m_Start.empty() && !m_Count.empty())
-    {
-        m_ShapeID = ShapeID::LocalArray;
-    }
-    else if (m_Shape.size() == 1 && m_Shape.front() == LocalValueDim)
-    {
-        m_ShapeID = ShapeID::LocalValue;
-        m_SingleValue = true;
-    }
-    else if (!m_Shape.empty() &&
-             std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) == 1)
-    {
-        m_ShapeID = ShapeID::JoinedArray;
     }
-    else if (!m_Shape.empty() &&
-             std::count(m_Shape.begin(), m_Shape.end(), JoinedDim) > 1)
+    else //(m_Shape.empty())
     {
-        throw std::invalid_argument("ERROR: variable can't have more than one "
-                                    "JoinedDim in shape argument, in call to "
-                                    "DefineVariable " +
-                                    m_Name + "\n");
+        if (m_Start.empty())
+        {
+            if (m_Count.empty())
+            {
+                m_ShapeID = ShapeID::GlobalValue;
+                m_SingleValue = true;
+            }
+            else if (m_Start.empty() && !m_Count.empty())
+            {
+                m_ShapeID = ShapeID::LocalArray;
+            }
+        }
+        else
+        {
+            throw std::invalid_argument(
+                "ERROR: if the "
+                "shape is empty, start must be empty as well, in call to "
+                "DefineVariable " +
+                m_Name + "\n");
+        }
     }
-    else
+
+    /* Extra checks for invalid settings */
+    if (m_ShapeID != ShapeID::LocalValue)
     {
-        throw std::invalid_argument("ERROR: the "
-                                    "combination of shape, start and count "
-                                    "arguments is inconsistent, in call to "
-                                    "DefineVariable " +
-                                    m_Name + "\n");
+        if ((!m_Shape.empty() &&
+             std::count(m_Shape.begin(), m_Shape.end(), LocalValueDim) > 0) ||
+            (!m_Start.empty() &&
+             std::count(m_Start.begin(), m_Start.end(), LocalValueDim) > 0) ||
+            (!m_Count.empty() &&
+             std::count(m_Count.begin(), m_Count.end(), LocalValueDim) > 0))
+        {
+            throw std::invalid_argument("ERROR: LocalValueDim is only "
+                                        "allowed in a {LocalValueDim} "
+                                        "shape in call to "
+                                        "DefineVariable " +
+                                        m_Name + "\n");
+        }
     }
 }
 
diff --git a/testing/adios2/interface/CMakeLists.txt b/testing/adios2/interface/CMakeLists.txt
index e229416de28347dbe46931805724e7d05bbdfdb2..e68ccfa6187ab17710e4bca93579ede6ded95079 100644
--- a/testing/adios2/interface/CMakeLists.txt
+++ b/testing/adios2/interface/CMakeLists.txt
@@ -6,4 +6,8 @@
 add_executable(TestADIOSInterfaceWrite TestADIOSInterfaceWrite.cpp)
 target_link_libraries(TestADIOSInterfaceWrite adios2 gtest gtest_main)
 
+add_executable(TestADIOSDefineVariable TestADIOSDefineVariable.cpp)
+target_link_libraries(TestADIOSDefineVariable adios2 gtest gtest_main)
+
 gtest_add_tests(TARGET TestADIOSInterfaceWrite)
+gtest_add_tests(TARGET TestADIOSDefineVariable)
\ No newline at end of file
diff --git a/testing/adios2/interface/TestADIOSDefineVariable.cpp b/testing/adios2/interface/TestADIOSDefineVariable.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..100f05fc4e7df69a6512a749cf7b3cf1eb705260
--- /dev/null
+++ b/testing/adios2/interface/TestADIOSDefineVariable.cpp
@@ -0,0 +1,355 @@
+#include <cstdint>
+
+#include <iostream>
+#include <stdexcept>
+
+#include <adios2.h>
+
+#include <gtest/gtest.h>
+
+class ADIOSDefineVariableTest : public ::testing::Test
+{
+public:
+    ADIOSDefineVariableTest() : adios(true), io(adios.DeclareIO("TestIO")) {}
+
+protected:
+    // virtual void SetUp() { }
+
+    // virtual void TearDown() { }
+
+    adios2::ADIOS adios;
+    adios2::IO &io;
+};
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalValue)
+{
+    // Define ADIOS global value
+    auto &globalvalue = io.DefineVariable<int>("globalvalue");
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalvalue),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalvalue.m_Shape.size(), 0);
+    EXPECT_EQ(globalvalue.m_Start.size(), 0);
+    EXPECT_EQ(globalvalue.m_Count.size(), 0);
+    EXPECT_EQ(globalvalue.m_Name, "globalvalue");
+    EXPECT_EQ(globalvalue.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalValue)
+{
+    // Define ADIOS local value (a value changing across processes)
+    auto &localvalue =
+        io.DefineVariable<int>("localvalue", {adios2::LocalValueDim});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localvalue),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localvalue.m_Shape.size(), 1);
+    EXPECT_EQ(localvalue.m_Shape[0], adios2::LocalValueDim);
+    EXPECT_EQ(localvalue.m_Start.size(), 0);
+    EXPECT_EQ(localvalue.m_Count.size(), 0);
+    EXPECT_EQ(localvalue.m_Name, "localvalue");
+    EXPECT_EQ(localvalue.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArray)
+{
+    // Define ADIOS global array
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>("globalarray", {100, n, 30},
+                                               {50, n / 2, 0}, {10, n / 2, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayWithSelections)
+{
+    // Define ADIOS global array with postponed size definition in SetSelection
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>("globalarray", {100, n, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    // Make a 3D selection to describe the local dimensions of the
+    // variable we write and its offsets in the global spaces
+    adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30});
+    globalarray.SetSelection(sel);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayConstantDims)
+{
+    // Define ADIOS global array with locked-down dimensions
+    std::size_t n = 50;
+    auto &globalarray = io.DefineVariable<int>(
+        "globalarray", {100, n, 30}, {50, n / 2, 0}, {10, n / 2, 30}, true);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(globalarray),
+                                  adios2::Variable<int> &>();
+
+    adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30});
+    EXPECT_THROW(globalarray.SetSelection(sel), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(globalarray.m_Shape.size(), 3);
+    EXPECT_EQ(globalarray.m_Shape[0], 100);
+    EXPECT_EQ(globalarray.m_Shape[1], n);
+    EXPECT_EQ(globalarray.m_Shape[2], 30);
+    EXPECT_EQ(globalarray.m_Start.size(), 3);
+    EXPECT_EQ(globalarray.m_Start[0], 50);
+    EXPECT_EQ(globalarray.m_Start[1], n / 2);
+    EXPECT_EQ(globalarray.m_Start[2], 0);
+    EXPECT_EQ(globalarray.m_Count.size(), 3);
+    EXPECT_EQ(globalarray.m_Count[0], 10);
+    EXPECT_EQ(globalarray.m_Count[1], n / 2);
+    EXPECT_EQ(globalarray.m_Count[2], 30);
+    EXPECT_EQ(globalarray.m_Name, "globalarray");
+    EXPECT_EQ(globalarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayInvalidLocalValueDim)
+{
+    // Define ADIOS global array
+    std::size_t n = 50;
+    adios2::Variable<int> *globalarray;
+    EXPECT_THROW(globalarray = &io.DefineVariable<int>(
+                     "globalarray", {100, adios2::LocalValueDim, 30},
+                     {50, n / 2, 0}, {10, n / 2, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArray)
+{
+    // Define ADIOS local array (no global dimensions, no offsets)
+    std::size_t n = 50;
+    auto &localarray =
+        io.DefineVariable<int>("localarray", {}, {}, {10, n / 2, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayWithSelection)
+{
+    // Define ADIOS local array with postponed size definition in SetSelection
+    std::size_t n = 50;
+    auto &localarray = io.DefineVariable<int>(
+        "localarray", {}, {},
+        {adios2::UnknownDim, adios2::UnknownDim, adios2::UnknownDim});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 0);
+    EXPECT_EQ(localarray.m_Count[1], 0);
+    EXPECT_EQ(localarray.m_Count[2], 0);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+
+    // Make a 3D selection to describe the local dimensions of the
+    // variable we write
+    adios2::SelectionBoundingBox sel({}, {10, n / 2, 30});
+    localarray.SetSelection(sel);
+
+    adios2::SelectionBoundingBox selbad({50, n / 2, 0}, {10, n / 2, 30});
+    EXPECT_THROW(localarray.SetSelection(selbad), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayConstantDims)
+{
+    // Define ADIOS local array with locked down dimensions
+    std::size_t n = 50;
+    auto &localarray =
+        io.DefineVariable<int>("localarray", {}, {}, {10, n / 2, 30}, true);
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(localarray),
+                                  adios2::Variable<int> &>();
+
+    adios2::SelectionBoundingBox sel({}, {10, n / 2, 30});
+    EXPECT_THROW(localarray.SetSelection(sel), std::invalid_argument);
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(localarray.m_Shape.size(), 0);
+    EXPECT_EQ(localarray.m_Start.size(), 0);
+    EXPECT_EQ(localarray.m_Count.size(), 3);
+    EXPECT_EQ(localarray.m_Count[0], 10);
+    EXPECT_EQ(localarray.m_Count[1], n / 2);
+    EXPECT_EQ(localarray.m_Count[2], 30);
+    EXPECT_EQ(localarray.m_Name, "localarray");
+    EXPECT_EQ(localarray.m_Type, "int");
+    EXPECT_EQ(localarray.m_ShapeID, adios2::ShapeID::LocalArray);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineLocalArrayInvalidOffsets)
+{
+    // Define ADIOS local array but try to add offsets
+    std::size_t n = 50;
+
+    adios2::Variable<int> *localarray;
+    EXPECT_THROW(localarray = &io.DefineVariable<int>(
+                     "localarray", {}, {50, n / 2, 0}, {10, n / 2, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayFirstDim)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    auto &joinedarray = io.DefineVariable<int>(
+        "joinedarray", {adios2::JoinedDim, n, 30}, {}, {10, n, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(joinedarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(joinedarray.m_Shape.size(), 3);
+    EXPECT_EQ(joinedarray.m_Shape[0], adios2::JoinedDim);
+    EXPECT_EQ(joinedarray.m_Shape[1], n);
+    EXPECT_EQ(joinedarray.m_Shape[2], 30);
+    EXPECT_EQ(joinedarray.m_Start.size(), 0);
+    EXPECT_EQ(joinedarray.m_Count.size(), 3);
+    EXPECT_EQ(joinedarray.m_Count[0], 10);
+    EXPECT_EQ(joinedarray.m_Count[1], n);
+    EXPECT_EQ(joinedarray.m_Count[2], 30);
+    EXPECT_EQ(joinedarray.m_Name, "joinedarray");
+    EXPECT_EQ(joinedarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArraySecondDim)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    auto &joinedarray = io.DefineVariable<int>(
+        "joinedarray", {n, adios2::JoinedDim, 30}, {0, 0, 0}, {n, 10, 30});
+
+    // Verify the return type is as expected
+    ::testing::StaticAssertTypeEq<decltype(joinedarray),
+                                  adios2::Variable<int> &>();
+
+    // Verify the dimensions, name, and type are correct
+    ASSERT_EQ(joinedarray.m_Shape.size(), 3);
+    EXPECT_EQ(joinedarray.m_Shape[0], n);
+    EXPECT_EQ(joinedarray.m_Shape[1], adios2::JoinedDim);
+    EXPECT_EQ(joinedarray.m_Shape[2], 30);
+    EXPECT_EQ(joinedarray.m_Start.size(), 3);
+    EXPECT_EQ(joinedarray.m_Start[0], 0);
+    EXPECT_EQ(joinedarray.m_Start[1], 0);
+    EXPECT_EQ(joinedarray.m_Start[2], 0);
+    EXPECT_EQ(joinedarray.m_Count.size(), 3);
+    EXPECT_EQ(joinedarray.m_Count[0], n);
+    EXPECT_EQ(joinedarray.m_Count[1], 10);
+    EXPECT_EQ(joinedarray.m_Count[2], 30);
+    EXPECT_EQ(joinedarray.m_Name, "joinedarray");
+    EXPECT_EQ(joinedarray.m_Type, "int");
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayTooManyJoinedDims)
+{
+    // Define ADIOS joined array
+    std::size_t n = 50;
+    adios2::Variable<int> *joinedarray;
+    EXPECT_THROW(joinedarray = &io.DefineVariable<int>(
+                     "joinedarray", {n, adios2::JoinedDim, adios2::JoinedDim},
+                     {}, {n, 50, 30}),
+                 std::invalid_argument);
+}
+
+TEST_F(ADIOSDefineVariableTest, DefineJoinedArrayInvalidStart)
+{
+    // Define ADIOS joined array
+    std::size_t n = 10;
+    std::size_t WrongValue = 1;
+    adios2::Variable<int> *joinedarray;
+    // Start must be empty or full zero array
+    EXPECT_THROW(
+        joinedarray = &io.DefineVariable<int>(
+            "joinedarray", {adios2::JoinedDim, 50}, {0, WrongValue}, {n, 50}),
+        std::invalid_argument);
+}
+
+int main(int argc, char **argv)
+{
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Init(nullptr, nullptr);
+#endif
+
+    ::testing::InitGoogleTest(&argc, argv);
+    int result = RUN_ALL_TESTS();
+
+#ifdef ADIOS2_HAVE_MPI
+    MPI_Finalize();
+#endif
+
+    return result;
+}