簡體   English   中英

Boost單元測試框架依賴關系執行順序

[英]Boost Unit Test Framework dependencies execution order

我正在嘗試在Boost單元測試框架中設置依賴項。 我發現tbat 線程有一個如何使用test_unit :: depends_on()方法的示例。 到目前為止,我可以寫一些魔術來解決它。 但是,UTF在執行期間不遵守測試依賴項。

方案:A BOOST_AUTO_TEST_CASE在另一個(B)之前聲明A,並且Adepend_on()B預期(期望)結果:框架檢測到依賴性並首先運行B,如果B成功,則運行A。 實際結果:跳過A,因為尚未運行的B已“失敗”(即,否/錯誤結果)。

現在,我的想法是對測試用例/套件進行拓撲排序,然后按排序順序運行它們。 為此,我創建了一個test_tree_visitor以遍歷套件並確定m_members test_suite成員的順序。

但是,m_members受保護,不能通過方法訪問。 由於我無法更改標頭((將使得升級到新版本更加困難等),並且BOOST_ *宏將類“硬編碼”為test_suite,因此,我在考慮以下黑客:

class member_accessible_test_suite : public test_suite
{
public:
    const std::vector<test_unit_id> *get_members() const { return &m_members; }
};

class dependency_order_visitor : public test_tree_visitor
{
public:
    virtual void visit( test_case const& tu)
    {}

    virtual bool test_suite_start( test_suite const& tu)
    {
        const member_accessible_test_suite *psuite(reinterpret_cast<const member_accessible_test_suite*>(&tu));
        const std::vector<test_unit_id> *pmembers(psuite->get_members());
        /* do something with pmembers */
        return true;
    }

    virtual void test_suite_finish( test_suite const& tu)
    {}

};

在Coliru上查看縮小版本

所以現在我的問題是:

  1. Boost庫通常設計得很好-我是否由於需要使用此功能而對單元測試設計存在誤解而犯了一個基本錯誤?

  2. 由於member_accessible_test_suite沒有數據並且僅添加函數,因此reinterpret_cast()是安全的還是進入UB國土的快速通道? 無論哪種方式,我都擔心在生產中使用如此可怕的技巧。

  3. 有沒有更好的方法?如果是,這在什么時候變成了XY問題?

當處理未通過任何機制公開的基類成員(但必須通過某些緊密的功能進行訪問且不得修改基類)時,以下方法似乎是最合適的:

鏈接: 訪問私有成員變量

在標准的14.7.2p8中可以找到關於此方法起作用的想法的理由:

通常的訪問檢查規則不適用於用於指定顯式實例化的名稱。 特別是,函數聲明器中使用的模板參數和名稱(包括參數類型,返回類型和異常規范)可以是通常無法訪問的私有類型或對象,並且模板可以是不能訪問的成員模板或成員函數。通常可以訪問。]

我自由地將其外包給兩個宏,有一天可能會派上用場。

與所有這些解決方法一樣-明智地使用!

/* The ROB_PRIVATE_MEMBER_INST() macro should be used for explicit instantiation of the template at the appropriate source/compilation unit
   The ROB_PRIVATE_MEMBER_ACCESS() macro should be used for access to the variable where required
*/
#define ROB_PRIVATE_MEMBER_INST(CLASS, TYPE, MEMBER)    \
template<typename T>                                    \
struct CLASS##_##MEMBER##_rob_tag {                     \
  typedef T CLASS::*type;                               \
  friend type get(CLASS##_##MEMBER##_rob_tag);          \
};                                                      \
template<typename Tag, typename Tag::type M>            \
struct CLASS##_##MEMBER##_rob_private                   \
{                                                       \
    friend typename Tag::type get(Tag) { return M; }    \
};                                                      \
template struct CLASS##_##MEMBER##_rob_private<         \
CLASS##_##MEMBER##_rob_tag<TYPE> , &CLASS::MEMBER>;     \
/**/

#define ROB_PRIVATE_MEMBER_ACCESS(CLASS, INSTANCE, TYPE, MEMBER) \
    (INSTANCE.*get(CLASS##_##MEMBER##_rob_tag<TYPE>()))          \
/**/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM