GTest交流与经验总结
Upcoming SlideShare
Loading in...5
×
 

GTest交流与经验总结

on

  • 22,234 views

 

Statistics

Views

Total Views
22,234
Views on SlideShare
20,408
Embed Views
1,826

Actions

Likes
13
Downloads
154
Comments
1

14 Embeds 1,826

http://www.cnblogs.com 1725
http://www.zhuaxia.com 31
http://xianguo.com 22
http://reader.youdao.com 14
http://zhuaxia.com 10
http://feeds.feedburner.com 8
http://static.slidesharecdn.com 7
http://twitter.com 3
http://cache.baiducontent.com 1
http://www.haogongju.net 1
http://www.4ucode.com 1
http://archive.cnblogs.com 1
http://c.yegeer.com 1
http://theoldreader.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    GTest交流与经验总结 GTest交流与经验总结 Presentation Transcript

    • GTest 交流 与经验总结 张长荣
    • 关于我
      • 张长荣 (coderzh)
      • 博客: http://www.cnblogs.com/coderzh
      • 参与项目:
        • 金山 WPS
        • 金山毒霸
        • 月影传说 Online
      • 工作内容:
        • 测试平台、测试工具、模块 ( 接口 ) 测试、性能测试、安全性测试……
    • 交 流
      • 从 GTest 说起
      • 经验分享
      • 讨论交流
    • GTest 缘分
      • Google 工程师
      • 技术交流
      • 留下印象
    • GTest 缘分
      • 自制单元测试框架: CppTestFramework
      分享:不要重复造轮子
    • GTest 缘分
      • 分享:不喜欢偷懒的测试不是好开发
    • GTest 缘分
      • 测试框架经常有 BUG 要改
      • 用的不爽,想加个功能
      分享: 不要让测试工作停下来,把框架维护的事情交给别人。
    • GTest 缘分
      • 发现 Google Test 是个好东西
    • GTest 缘分
      • 使用 Google Test 的理由:
        • 简单
        • 好用
        • 优秀的人在维护
    • 《玩转 GTest 》 zhanyong.wan from Google
    • 《玩转 GTest 》
      • 分享:
      • 只要你想,
      • 没有什么不可能。
    • 开始说 Gtest
      • 单元测试框架: CppUnit, NUnit, JUnit, LuaUnit,PhpUnit……
      • Google C++ Testing Framework (gtest)
      XUnit
    • GTest 的特点 (1)
      • 跨平台: Linux, Mac OS, Windows...
      • 支持 Nonfatal 断言 (EXPECT_*)
      • 支持定制断言失败时的输出 :
      • ASSERT_EQ(5, Foo(i)) << &quot; where i = &quot; << i;
    • GTest 的特点 (2)
      • 自动检测测试案例,不需要自己指定。
      • 轻松扩展断言宏 ( EXPECT_PRED* )
      • 支持 Death Tests
      • 参数化测试
      • 丰富的命令行参数选项: ( --gtest_filter=*.* )
    • GTest 的特点 (3)
      • 使用简单:
        • 引用头文件
        • 引用 gtest.lib
        • 主函数添加:
        • int _tmain(int argc, _TCHAR* argv[])
        • {
        • testing::InitGoogleTest(&argc, argv);
        • return RUN_ALL_TESTS();
        • }
        • TEST, TEST_F, TEST_P 编写测试案例
    • GTest 示例
      • #include <gtest/gtest.h>
      • TEST (FooTest, HandleNoneZeroInput)
      • {
      • EXPECT_EQ (6, Foo(30, 18));
      • }
    • XUnit
      • Test case
      • Test fixtures
      • Test suites
      • Test execution
      • Assertions
    • XUnit 基础 分享:测试代码尽量简洁、清晰。
    • XUnit 基础
      • import unittest
      • class TestFoo(unittest.TestCase):
      • def setUp (self):
      • pass
      • def tearDown (self):
      • pass
      • def TestCase1(self):
      • self.assertEqual(2, 2)
    • XUnit 基础
      • [TestFixture]
      • public class FooTest {
      • [SetUp]
      • public void Init() { }
      • [TearDown]
      • public void UnInit() { }
      • [Test]
      • public void TestCase1() {
      • Assert.AreEqual(2, 2);
      • }
      • }
    • XUnit 基础
      • class FooTest:public testing::Test {
      • protected:
      • virtual void SetUp() { }
      • virtual void TearDown() { }
      • };
      • TEST_F(FooTest, Test) {
      • EXPECT_EQ(1, 1);
      • }
    • XUnit 基础
      • Test Fixture :
        • Fresh Fixture
        • Shared Fixture
      分享: 尽量避免 Slow Tests 。
    • XUnit 基础
      • class FooTest : public testing::Test
      • {
      • protected:
      • static void SetUpTestCase () { }
      • static void TearDownTestCase () { }
      • };
    • GTest 全局 Setup/TearDown
      • class FooEnvironment : public testing::Environment {
      • public:
      • virtual void SetUp () { }
      • virtual void TearDown () { }
      • };
    • GTest 全局 Setup/TearDown
      • int _tmain(int argc, _TCHAR* argv[])
      • {
      • testing::AddGlobalTestEnvironment(new FooEnvironment);
      • testing::InitGoogleTest(&argc, argv);
      • return RUN_ALL_TESTS();
      • }
    • Setup 异常机制
      • 发生 Fatal Failure 后,
      • Global SetUp - 直接退出,不执行任何案例
      • SetUpTestCase - 不影响后面的案例执行
      • Test Fixture SetUp - 当前案例退出,不执行
      HasFatalFailure()
    • XUnit 基础 - 断言
      • EXPECT_*
        • EXPECT_EQ
        • EXPECT_TRUE
        • EXPECT_THROW
        • EXPECT_HRESULT_SUCCEEDED
        • ...
      • ASSERT_*
    • XUnit 基础 - 断言
      • EXPECT_PRED_* / ASSERT_PRED_*
        • 自定义断言
        • 所有类型的断言实现的基础
      分享: 错误信息尽量详细和准确,尽量避免调试。
    • XUnit 基础 - 断言
      • TEST(FooTest, HandleFail)
      • {
      • int m = 3;
      • int n = 6
      • EXPECT_PRED_FORMAT3 (AssertFoo, m, n, 2);
      • }
      • 结果:
      • error: m(3) 和 n(6) 的最大公约数应该是: 3 而不是: 2
    • XUnit 基础 - 断言
      • testing::AssertionResult AssertFoo (const char* m_expr, const char* n_expr, const char* k_expr, int m, int n, int k) {
      • if (Foo(m, n) == k) return testing:: AssertionSuccess ();
      • testing::Message msg;
      • msg << m_expr << &quot;(&quot; << m << &quot;)&quot; << &quot; 和 &quot;
      • << n_expr << &quot;(&quot; << n << &quot;)&quot;
      • << &quot; 的最大公约数应该是: &quot; << Foo(m, n) << &quot; 而不是: &quot; << k_expr;
      • return testing:: AssertionFailure (msg);
      • }
    • XUnit 基础 - 断言
      • ...
      • #define EXPECT_LE (val1, val2)
      • #define EXPECT_LT (val1, val2)
      • #define EXPECT_GE (val1, val2)
      • ...
      • EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
      • EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
      • EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
    • XUnit 基础 - 断言
      • #define GTEST_IMPL_CMP_HELPER_(op_name, op)
      • template <typename T1, typename T2>
      • AssertionResult CmpHelper##op_name (const char* expr1, const char* expr2, const T1& val1, const T2& val2) {
      • if (val1 op val2) { return AssertionSuccess (); }
      • else {
      • }
      • }
      • return AssertionFailure(msg);
      • msg << &quot;Expected: (&quot; << expr1 << &quot;) &quot; #op &quot; (&quot; << expr2 << &quot;), actual: &quot; << FormatForComparisonFailureMessage(val1,val2) << &quot; vs &quot; << FormatForComparisonFailureMessage(val2, val1);
      • Message msg;
    • XUnit 基础 - 断言
      • ASSERT_* 和 EXPECT_* 区别
      • #define GTEST_FATAL_FAILURE_(message)
      • return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
      • #define GTEST_NONFATAL_FAILURE_(message)
      • GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
    • XUnit 基础 - 断言
      • ASSERT_*
        • 只是当前函数返回,并非测试案例返回。
        • 所在函数的返回值必须为 void 。
      int Func() // Wrong { ASSERT_EQ(1, 2); } TEST(TestFoo, TestFoo) { Func(); ASSERT_EQ(1, 0); } void Func() { ASSERT_EQ (1, 2); } TEST(TestFoo, TestFoo) { Func(); ASSERT_EQ (1, 0); }
    • GTest - 参数化测试
      • 参数化测试(数据驱动测试)
      bool IsPrime (int n ) { ... } -1 0 1 2 13 99 ...
    • GTest - 参数化测试
      • 可能,我们会这样写:
      TEST(IsPrimeTest, TestAll) { EXPECT_FALSE( IsPrime(-1) ); EXPECT_FALSE( IsPrime(0) ); EXPECT_FALSE( IsPrime(1) ); EXPECT_TRUE( IsPrime(2) ); EXPECT_TRUE( IsPrime(13) ); ... }
    • GTest - 参数化测试 分享: 一个测试案例,理想情况下,只需要一个断言。
    • GTest - 参数化测试
      • 这就是理想情况:
      • TEST_P (IsPrimeParamTest, TrueReturn)
      • {
      • int n = GetParam();
      • EXPECT_TRUE (IsPrime(n));
      • }
    • GTest - 参数化测试
      • class IsPrimeParamTest : public::testing:: TestWithParam<int>
      • {
      • }
      • INSTANTIATE_TEST_CASE_P (TrueReturn, IsPrimeParamTest, testing::Values( 2,13,17,23 ));
    • GTest - 运行参数
      • 系统环境变量
      • 命令行参数
        • --gtest_filter = *.*
      • 代码中指定 FLAG
        • testing::GTEST_FLAG(output) = &quot;xml:&quot;;
    • GTest - 运行参数
      • --gtest_list_tests
      • --gtest_filter
      • --gtest_also_run_disabled_tests
      • --gtest_repeat=[COUNT]
      • --gtest_output=xml:
      • --gtest_break_on_failure
      • --gtest_throw_on_failure
    • 小技巧
    • 小技巧
      • 获取当前测试案例名称:
      • const ::testing::TestInfo* const test_info =
      • ::testing::UnitTest::GetInstance()->current_test_info() ;
      • printf(&quot;We are in test %s of test case %s.n&quot;,
      • test_info->name() , test_info->test_case_name() );
    • GTest
      • GTest 就讲到这里,
      • 下面说说我对测试开发的一些理解
    • 经验交流
      • 分享:做 有用 的测试
      最高原则
    • 经验交流
      • 分享:
      • 测试案例执行的次数越多,价值越大!
    • 经验交流
      • 分享:
      • 稳定的测试案例才有效
    • 经验交流
      • 正确理解 Mock:
        • Dummy Object
        • Test Stub
        • Test Spy
        • Mock Object
        • Fake Object
    • Google Mock
      • TEST(PainterTest, CanDrawSomething) {
      • MockTurtle turtle;
      • EXPECT_CALL(turtle, PenDown())
      • .Times(AtLeast(1));
      • Painter painter(&turtle);
      • EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
      • }
    • BDD
      • BDD (Behavior Driven Development)
      As a [X] I want [Y] so that [Z] Given some initial context When an event occurs, then ensure some outcomes. 故事模板 场景模板
    • BDD
      • 一个例子:
      Given I am not logged in When I log in as Morgan with a password SecretPassw0rd Then I should see a message, &quot;Welcome, Morgan!&quot;
    • BDD
      • using NBehave.Narrator.Framework;
      • using NBehave.Spec.NUnit;
      • [ActionSteps]
      • public class UserLogsInSuccessfully {
      • [ Given (&quot;I am not logged in&quot;)]
      • public void LogOut() { _currentPage.click(&quot;logout&quot;); }
      • [ When (&quot;I log in as $username with a password $password&quot;)]
      • publicvoid LogIn(string username, string password) { _currentPage.click(&quot;login&quot;); }
      • [ Then (&quot;I should see a message, &quot;$message&quot;&quot;)]
      • publicvoid CheckMessage(string message) {
      • _currentPage.ToString().ShouldContain(message);
      • }
      • }
    • 我的实践
      • TEST_F(NormalUpdateTest, OnlineUpdateFlow)
      • {
      • ASSERT_TRUE(Delete(TheFile(L&quot;infoc.dat&quot;)->WhichIn(InstallDirectory)));
      • CallUpdate(WithCommandLine(L&quot;&quot;),
      • AndWithInternalParameter(L&quot;-online -custom&quot;));
      • EXPECT_TRUE(TheFile(L&quot;infoc.dat&quot;)->ExistsIn(InstallDirectory));
      • EXPECT_TRUE(TheFile(L&quot;infoc.dat&quot;)->WhichIn(InstallDirectory)->
      • HasTheSameCRCValueAs(TheFile(L&quot;infoc.dat&quot;)->
      • CRCValueInIndexDat()));
      • }
    • Principles
      • Write the Tests First
      • Design for Testability
      • Use the Front Door First
      • Communicate Intent
      • Don’t Modify the SUT
      • Keep Tests Independent
      • Isolate the SUT
      • Minimize Test Overlap
    • Principles
      • Minimize Untestable Code
      • Keep Test Logic Out of Production Code
      • Verify One Condition per Test
      • Test Conerns Separtely
      • Ensure Commensurate Effort and Responsibility
    • 做有用的测试! 谢谢大家