GoogleTest: จะข้ามการทดสอบได้อย่างไร


121

ใช้ Google Test 1.6 (Windows 7, Visual Studio C ++) ฉันจะปิดการทดสอบที่กำหนดได้อย่างไร (aka ฉันจะป้องกันไม่ให้การทดสอบทำงานได้อย่างไร) ฉันสามารถทำอะไรได้บ้างนอกจากแสดงความคิดเห็นในการทดสอบทั้งหมด

คำตอบ:


179

เอกสารสำหรับ Google ทดสอบ 1.7 แนะนำ :

"หากคุณมีการทดสอบที่เสียซึ่งคุณไม่สามารถแก้ไขได้ในทันทีคุณสามารถเพิ่มคำนำหน้า DISABLED_ ลงในชื่อซึ่งจะไม่รวมการทดสอบดังกล่าวออกจากการดำเนินการ"

ตัวอย่าง:

// Tests that Foo does Abc.
TEST(FooTest, DISABLED_DoesAbc) { ... }

class DISABLED_BarTest : public ::testing::Test { ... };

// Tests that Bar does Xyz.
TEST_F(DISABLED_BarTest, DoesXyz) { ... }

1
เพิ่งเจอเหมือนกันและตัวกรอง
ผู้ใช้

@Bill ฉันพบมันก่อนที่คุณจะโพสต์ความคิดเห็นของคุณ ... (และฉันใส่ไว้เป็นคำตอบด้วย) จากนั้นฉันก็ลบความคิดเห็นออกโดยคิดว่ามันล้าสมัย ... แต่นั่นเป็นข้อมูลที่ดีจริงๆ! +1
Kiril

67

คุณยังสามารถเรียกใช้การทดสอบชุดย่อยได้ตามเอกสาร:

เรียกใช้ชุดย่อยของการทดสอบ

โดยค่าเริ่มต้นโปรแกรมทดสอบของ Google จะเรียกใช้การทดสอบทั้งหมดตามที่ผู้ใช้กำหนด บางครั้งคุณต้องการเรียกใช้การทดสอบเพียงบางส่วนเท่านั้น (เช่นสำหรับการดีบักหรือตรวจสอบการเปลี่ยนแปลงอย่างรวดเร็ว) หากคุณตั้งค่าตัวแปรสภาพแวดล้อม GTEST_FILTER หรือแฟล็ก --gtest_filter เป็นสตริงตัวกรอง Google Test จะเรียกใช้การทดสอบที่มีชื่อเต็ม (ในรูปแบบของ TestCaseName.TestName) ตรงกับตัวกรองเท่านั้น

รูปแบบของตัวกรองคือ ":" - รายการรูปแบบตัวแทนที่คั่น (เรียกว่ารูปแบบเชิงบวก) ตามด้วยรายการรูปแบบ "-" และอีกรายการหนึ่ง ":" (เรียกว่ารูปแบบเชิงลบ) การทดสอบจะจับคู่ตัวกรองก็ต่อเมื่อตรงกับรูปแบบเชิงบวกใด ๆ แต่ไม่ตรงกับรูปแบบเชิงลบใด ๆ

รูปแบบอาจมี "*" (ตรงกับสตริงใดก็ได้) หรือ "?" (จับคู่อักขระเดี่ยวใด ๆ ) เพื่อความสะดวกตัวกรอง '* -NegativePatterns' ยังสามารถเขียนเป็น '-NegativePatterns'

ตัวอย่างเช่น:

./foo_test Has no flag, and thus runs all its tests.
./foo_test --gtest_filter=* Also runs everything, due to the single match-everything * value.
./foo_test --gtest_filter=FooTest.* Runs everything in test case FooTest.
./foo_test --gtest_filter=*Null*:*Constructor* Runs any test whose full name contains either "Null" or "Constructor".
./foo_test --gtest_filter=-*DeathTest.* Runs all non-death tests.
./foo_test --gtest_filter=FooTest.*-FooTest.Bar Runs everything in test case FooTest except FooTest.Bar. 

ไม่ใช่วิธีแก้ปัญหาที่สวยที่สุด แต่ใช้ได้ผล


24

ตอนนี้คุณสามารถใช้GTEST_SKIP()มาโครเพื่อข้ามการทดสอบที่รันไทม์ได้ตามเงื่อนไข ตัวอย่างเช่น:

TEST(Foo, Bar)
{
    if (blah)
        GTEST_SKIP();

    ...
}

โปรดทราบว่านี่เป็นคุณลักษณะล่าสุดดังนั้นคุณอาจต้องอัปเดตไลบรารี GoogleTest เพื่อใช้งาน


ฟีเจอร์นี้ยังไม่เปิดตัว ไม่น่าจะรวมอยู่ในสาขา 1.8.x เนื่องจากยอมรับเฉพาะการแก้ไขเท่านั้น 1.9 ยังไม่พร้อมใช้งานยังไม่ได้ประกาศในขณะนี้
ocroquette

2
GTEST_SKIP()มีให้ตั้งแต่ 1.10.0
mattdibi

น่าเศร้าที่เอกสารยังหายากในเรื่องนี้ ดูเหมือนว่าจะมีด้วยGTEST_SKIP_("some message")(โปรดสังเกตขีดล่าง)
Matthäus Brandl

19

นี่คือนิพจน์เพื่อรวมการทดสอบที่ชื่อมีสตริง foo1 หรือ foo2 อยู่ในนั้นและไม่รวมการทดสอบที่มีชื่อมีสตริง bar1 หรือ bar2 อยู่ในนั้น:

--gtest_filter=*foo1*:*foo2*-*bar1*:*bar2*

10

ฉันชอบที่จะทำในรหัส:

// Run a specific test only
//testing::GTEST_FLAG(filter) = "MyLibrary.TestReading"; // I'm testing a new feature, run something quickly

// Exclude a specific test
testing::GTEST_FLAG(filter) = "-MyLibrary.TestWriting"; // The writing test is broken, so skip it

ฉันสามารถแสดงความคิดเห็นทั้งสองบรรทัดเพื่อเรียกใช้การทดสอบทั้งหมดยกเลิกการแสดงความคิดเห็นในบรรทัดแรกเพื่อทดสอบคุณสมบัติเดียวที่ฉันกำลังตรวจสอบ / กำลังดำเนินการหรือยกเลิกการแสดงความคิดเห็นในบรรทัดที่สองหากการทดสอบเสีย แต่ฉันต้องการทดสอบอย่างอื่น
คุณยังสามารถทดสอบ / ไม่รวมชุดคุณสมบัติได้โดยใช้สัญลักษณ์แทนและเขียนรายการ "MyLibrary.TestNetwork *" หรือ "-MyLibrary.TestFileSystem *"


นี่เป็นทางออกที่ยอดเยี่ยม ฉันใช้มันเพื่อยกเว้นการทดสอบบางอย่างโดยค่าเริ่มต้นหากตัวกรองว่างเปล่า สามารถเปิดใช้งานด้วยexport GTEST_FILTER='*'ไฟล์.
Timmmm

ที่จริงใช้ไม่ได้เพราะค่าเริ่มต้นคือ " *" not "" ฉันจะใช้ตัวแปรสภาพแวดล้อมอื่นที่แทนที่ตัวกรองแทน
Timmmm

คุณกำหนด "ตัวกรอง" ไว้ที่ใด มันเป็นสาย?
beasone

ฉันไม่ได้กำหนดดังนั้นฉันคิดว่าต้องเป็น global ที่รวมจาก gtest / gtest.h?
pilkch


5

สำหรับแนวทางอื่นคุณสามารถรวมการทดสอบของคุณไว้ในฟังก์ชันและใช้การตรวจสอบเงื่อนไขตามปกติที่รันไทม์เพื่อดำเนินการตามที่คุณต้องการเท่านั้น

#include <gtest/gtest.h>

const bool skip_some_test = true;

bool some_test_was_run = false;

void someTest() {
   EXPECT_TRUE(!skip_some_test);
   some_test_was_run = true;
}

TEST(BasicTest, Sanity) {
   EXPECT_EQ(1, 1);
   if(!skip_some_test) {
      someTest();
      EXPECT_TRUE(some_test_was_run);
   }
}

สิ่งนี้มีประโยชน์สำหรับฉันเนื่องจากฉันพยายามเรียกใช้การทดสอบบางอย่างเฉพาะเมื่อระบบรองรับ dual stack IPv6

ในทางเทคนิคแล้วสิ่งที่ดูอัลสแต็คไม่ควรเป็นการทดสอบหน่วยเนื่องจากขึ้นอยู่กับระบบ แต่ฉันไม่สามารถทำการทดสอบการผสานรวมได้จนกว่าฉันจะทดสอบว่ามันใช้งานได้จริงและสิ่งนี้ทำให้มั่นใจได้ว่าจะไม่รายงานความล้มเหลวเมื่อไม่ใช่ความผิดปกติของรหัส

สำหรับการทดสอบนั้นฉันมีวัตถุต้นขั้วที่จำลองระบบรองรับ dualstack (หรือขาด) โดยการสร้างซ็อกเก็ตปลอม

ข้อเสียเพียงอย่างเดียวคือผลการทดสอบและจำนวนการทดสอบจะเปลี่ยนไปซึ่งอาจทำให้เกิดปัญหากับสิ่งที่ตรวจสอบจำนวนการทดสอบที่ประสบความสำเร็จ

คุณยังสามารถใช้ ASSERT_ * แทน EQUAL_ * ยืนยันจะเกี่ยวกับการทดสอบที่เหลือหากล้มเหลว ป้องกันไม่ให้มีการถ่ายโอนข้อมูลซ้ำซ้อนจำนวนมากไปยังคอนโซล


4

ฉันมีความต้องการแบบเดียวกันสำหรับการทดสอบตามเงื่อนไขและฉันพบวิธีแก้ปัญหาที่ดี ฉันกำหนดมาโคร TEST_C ที่ทำงานเหมือนแมโคร TEST_F แต่มีพารามิเตอร์ที่สามซึ่งเป็นนิพจน์บูลีนซึ่งประเมินรันไทม์ใน main.cpp ก่อนการทดสอบจะเริ่มขึ้น การทดสอบที่ประเมินค่าเท็จจะไม่ดำเนินการ มาโครน่าเกลียด แต่ดูเหมือนว่า:

#pragma once
extern std::map<std::string, std::function<bool()> >* m_conditionalTests;
#define TEST_C(test_fixture, test_name, test_condition)\
class test_fixture##_##test_name##_ConditionClass\
{\
    public:\
    test_fixture##_##test_name##_ConditionClass()\
    {\
        std::string name = std::string(#test_fixture) + "." + std::string(#test_name);\
        if (m_conditionalTests==NULL) {\
            m_conditionalTests = new std::map<std::string, std::function<bool()> >();\
        }\
        m_conditionalTests->insert(std::make_pair(name, []()\
        {\
            DeviceInfo device = Connection::Instance()->GetDeviceInfo();\
            return test_condition;\
        }));\
    }\
} test_fixture##_##test_name##_ConditionInstance;\
TEST_F(test_fixture, test_name)

นอกจากนี้ใน main.cpp ของคุณคุณต้องใช้ลูปนี้เพื่อยกเว้นการทดสอบที่ประเมินค่าเท็จ:

// identify tests that cannot run on this device
std::string excludeTests;
for (const auto& exclusion : *m_conditionalTests)
{
    bool run = exclusion.second();
    if (!run)
    {
        excludeTests += ":" + exclusion.first;
    }
}

// add the exclusion list to gtest
std::string str = ::testing::GTEST_FLAG(filter);
::testing::GTEST_FLAG(filter) = str + ":-" + excludeTests;

// run all tests
int result = RUN_ALL_TESTS();

คุณกำหนด "ตัวกรอง" ใน std :: string str = :: testing :: GTEST_FLAG (filter) ได้อย่างไร?
beasone
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.