代码之家  ›  专栏  ›  技术社区  ›  Poni

代码覆盖率(C++代码执行路径)

  •  9
  • Poni  · 技术社区  · 16 年前

    假设我有这个代码:

    int function(bool b)
    {
        // execution path 1
        int ret = 0;
        if(b)
        {
            // execution path 2
            ret = 55;
        }
        else
        {
            // execution path 3
            ret = 120;
        }
        return ret;
    }
    

    我需要某种机制来确保代码已进入任何可能的路径,即上面代码中的执行路径1、2和3。

    我考虑过有一个全局函数、向量和宏。
    这个宏将简单地调用这个函数,将源文件名和代码行作为参数传递,这个函数将通过向向量插入宏传递的信息,将其标记为“选中”。

    问题是,我不会看到任何关于没有“检查”的路径的信息。
    我知道怎么做吗?如何在编译时“注册”一行代码,所以在运行时我可以看到它还没有“检查”?

    我希望我明白。

    6 回复  |  直到 12 年前
        1
  •  7
  •   Maja Piechotka    16 年前

    通常覆盖公用设施(如 gcov )与编译器一起提供。但是,请注意,他们通常只给你C0保险。即。

    • c0-每行至少执行一次。请注意 a ? b : c 即使只使用了一个分支,也标记为已执行。
    • c1-每个分支至少执行一次。
    • c2-每个路径至少执行一次

    因此,即使您的测试显示100%的C0覆盖率,您也可能无法捕捉代码中的每一条路径——而且可能您没有时间去做(相对于分支,路径数呈指数增长)。但是,最好知道你是否有10%的c2或70%的c2(或0.1%的c2)。

        2
  •  2
  •   Greg Hewgill    16 年前

    通常,编译器会提供一个实用程序来进行这种代码覆盖率分析。例如,GCC具有 gcov 实用工具。

        3
  •  2
  •   graham.reeds    16 年前

    您需要一个代码覆盖计划(gcov、bulseye、dev partner)和单元测试(unittest++、cppunit等)。您编写的测试将测试该函数。

    TEST( UnitTestFunction )
    {
        CHECK( function(true) == 55 );
        CHECK( function(false) == 120 );
    }
    

    在这种情况下,单元测试不仅检查完整性(尽管它们仍然如此),而且还测试覆盖率。

        4
  •  1
  •   Ira Baxter    16 年前

    尝试 SD C++ TestCoverage 对于VisualStudio兼容的测试覆盖率工具。我相信它实际上会告诉你关于 A?B:C 也是。

        5
  •  0
  •   Jorg B Jorge    16 年前

    你可以使用 文件 线 预处理器指令:

    #define TRACE(msg) MyTraceNotify(msg,__FILE__,__LINE__)
    

    只需将trace(msg)宏插入代码中要跟踪的位置,使用自定义消息,然后编写mytracenotify函数。

    void MyTraceNotify(const char *msg, const char *filename, ULONG line)
    {
        /* Put your code here... */    
    }
    
        6
  •  0
  •   Community Mohan Dere    9 年前

    问题是,我不会看到任何关于没有“检查”的路径的信息。

    如果这意味着,换句话说,你不仅要寻找一组实际执行的代码点,而且要寻找一组以某种方式被“标记”的代码点,这些代码点可能会被执行以最终报告差异,那么我可能会 dangerous 解决方案。它适用于我的MSVC 2010和2013。

    该方法是利用静态变量的预编程初始化初始化,但由于所有代码点都在函数中,因此,“静态ANKER点”必须以某种方式存在,因此,C++特性 delayed initialization of static function variables 必须克服。

    这似乎可以通过一个带有静态成员变量(progloc_u)的模板类(x)添加一个间接寻址来强制每个模板参数的初始化,而这个模板参数又是一个包装结构,它传输所需的信息(u)。 文件 .“at line”, 线 .)

    把这些放在一起,实现这一点的最重要的代码可能如下所示:

    template <class T> class X {
    public:
        static T progloc_;
    };
    template <class T> T X<T>::progloc_;
    
    #define TRACE_CODE_POINT \
        struct ProgLocation { \
        public: \
            std::string loc_; \
            ProgLocation() : loc_(std::string(__FILE__ " at line " S__LINE__)) \
            { \
                TestFw::CodePoints::Test::imHere(loc_); \
            } \
        }; \
        TestFw::CodePoints::X<ProgLocation> dummy; \
        TestFw::CodePoints::Test::iGotCalled(dummy.progloc_.loc_);
    

    程序定位中使用的s_uuu线技巧来自 here on SO .

    #define S(x) #x
    #define S_(x) S(x)
    #define S__LINE__ S_(__LINE__)
    

    要跟踪,请使用以下内容:

    class Test
    {
    private:
        typedef std::set<std::string> TFuncs;
        static TFuncs registeredFunctions;
        static TFuncs calledFunctions;
    public:
        static int imHere(const std::string fileAndLine)
        {
            assert(registeredFunctions.find(fileAndLine) == registeredFunctions.end());
            registeredFunctions.insert(fileAndLine);
            return 0;
        }
        static void iGotCalled(const std::string fileAndLine)
        {
            if (calledFunctions.find(fileAndLine) == calledFunctions.end())
                calledFunctions.insert(fileAndLine);
        }
        static void report()
        {
            for (TFuncs::const_iterator rfIt = registeredFunctions.begin(); rfIt != registeredFunctions.end(); ++rfIt)
                if (calledFunctions.find(*rfIt) == calledFunctions.end())
                    std::cout << (*rfIt) << " didn't get called" << std::endl;
        }
    };
    

    也许这种方法有很多问题,我还没有看到,并使其适用于您的案例,正如其他人指出的,使用静态代码分析工具在大多数情况下是更好的解决方案。

    编辑:

    刚刚发现提供的解决方案已经在另一个上下文中讨论过:

    non-deferred-static-member-initialization-for-templates-in-gcc

    推荐文章