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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

GTest交流与经验总结

21,449

Published on

Published in: Technology
1 Comment
13 Likes
Statistics
Notes
No Downloads
Views
Total Views
21,449
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
159
Comments
1
Likes
13
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. GTest 交流 与经验总结 张长荣
  • 2. 关于我
    • 张长荣 (coderzh)
    • 博客: http://www.cnblogs.com/coderzh
    • 参与项目:
      • 金山 WPS
      • 金山毒霸
      • 月影传说 Online
    • 工作内容:
      • 测试平台、测试工具、模块 ( 接口 ) 测试、性能测试、安全性测试……
  • 3. 交 流
    • 从 GTest 说起
    • 经验分享
    • 讨论交流
  • 4. GTest 缘分
    • Google 工程师
    • 技术交流
    • 留下印象
  • 5. GTest 缘分
    • 自制单元测试框架: CppTestFramework
    分享:不要重复造轮子
  • 6. GTest 缘分
    • 分享:不喜欢偷懒的测试不是好开发
  • 7. GTest 缘分
    • 测试框架经常有 BUG 要改
    • 用的不爽,想加个功能
    分享: 不要让测试工作停下来,把框架维护的事情交给别人。
  • 8. GTest 缘分
    • 发现 Google Test 是个好东西
  • 9. GTest 缘分
    • 使用 Google Test 的理由:
      • 简单
      • 好用
      • 优秀的人在维护
  • 10. 《玩转 GTest 》 zhanyong.wan from Google
  • 11. 《玩转 GTest 》
    • 分享:
    • 只要你想,
    • 没有什么不可能。
  • 12. 开始说 Gtest
    • 单元测试框架: CppUnit, NUnit, JUnit, LuaUnit,PhpUnit……
    • Google C++ Testing Framework (gtest)
    XUnit
  • 13. GTest 的特点 (1)
    • 跨平台: Linux, Mac OS, Windows...
    • 支持 Nonfatal 断言 (EXPECT_*)
    • 支持定制断言失败时的输出 :
    • ASSERT_EQ(5, Foo(i)) << &quot; where i = &quot; << i;
  • 14. GTest 的特点 (2)
    • 自动检测测试案例,不需要自己指定。
    • 轻松扩展断言宏 ( EXPECT_PRED* )
    • 支持 Death Tests
    • 参数化测试
    • 丰富的命令行参数选项: ( --gtest_filter=*.* )
  • 15. GTest 的特点 (3)
    • 使用简单:
      • 引用头文件
      • 引用 gtest.lib
      • 主函数添加:
      • int _tmain(int argc, _TCHAR* argv[])
      • {
      • testing::InitGoogleTest(&argc, argv);
      • return RUN_ALL_TESTS();
      • }
      • TEST, TEST_F, TEST_P 编写测试案例
  • 16. GTest 示例
    • #include <gtest/gtest.h>
    • TEST (FooTest, HandleNoneZeroInput)
    • {
    • EXPECT_EQ (6, Foo(30, 18));
    • }
  • 17. XUnit
    • Test case
    • Test fixtures
    • Test suites
    • Test execution
    • Assertions
  • 18. XUnit 基础 分享:测试代码尽量简洁、清晰。
  • 19. XUnit 基础
    • import unittest
    • class TestFoo(unittest.TestCase):
    • def setUp (self):
    • pass
    • def tearDown (self):
    • pass
    • def TestCase1(self):
    • self.assertEqual(2, 2)
  • 20. XUnit 基础
    • [TestFixture]
    • public class FooTest {
    • [SetUp]
    • public void Init() { }
    • [TearDown]
    • public void UnInit() { }
    • [Test]
    • public void TestCase1() {
    • Assert.AreEqual(2, 2);
    • }
    • }
  • 21. XUnit 基础
    • class FooTest:public testing::Test {
    • protected:
    • virtual void SetUp() { }
    • virtual void TearDown() { }
    • };
    • TEST_F(FooTest, Test) {
    • EXPECT_EQ(1, 1);
    • }
  • 22. XUnit 基础
    • Test Fixture :
      • Fresh Fixture
      • Shared Fixture
    分享: 尽量避免 Slow Tests 。
  • 23. XUnit 基础
    • class FooTest : public testing::Test
    • {
    • protected:
    • static void SetUpTestCase () { }
    • static void TearDownTestCase () { }
    • };
  • 24. GTest 全局 Setup/TearDown
    • class FooEnvironment : public testing::Environment {
    • public:
    • virtual void SetUp () { }
    • virtual void TearDown () { }
    • };
  • 25. GTest 全局 Setup/TearDown
    • int _tmain(int argc, _TCHAR* argv[])
    • {
    • testing::AddGlobalTestEnvironment(new FooEnvironment);
    • testing::InitGoogleTest(&argc, argv);
    • return RUN_ALL_TESTS();
    • }
  • 26. Setup 异常机制
    • 发生 Fatal Failure 后,
    • Global SetUp - 直接退出,不执行任何案例
    • SetUpTestCase - 不影响后面的案例执行
    • Test Fixture SetUp - 当前案例退出,不执行
    HasFatalFailure()
  • 27. XUnit 基础 - 断言
    • EXPECT_*
      • EXPECT_EQ
      • EXPECT_TRUE
      • EXPECT_THROW
      • EXPECT_HRESULT_SUCCEEDED
      • ...
    • ASSERT_*
  • 28. XUnit 基础 - 断言
    • EXPECT_PRED_* / ASSERT_PRED_*
      • 自定义断言
      • 所有类型的断言实现的基础
    分享: 错误信息尽量详细和准确,尽量避免调试。
  • 29. XUnit 基础 - 断言
    • TEST(FooTest, HandleFail)
    • {
    • int m = 3;
    • int n = 6
    • EXPECT_PRED_FORMAT3 (AssertFoo, m, n, 2);
    • }
    • 结果:
    • error: m(3) 和 n(6) 的最大公约数应该是: 3 而不是: 2
  • 30. 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);
    • }
  • 31. 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)
  • 32. 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;
  • 33. 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)
  • 34. 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); }
  • 35. GTest - 参数化测试
    • 参数化测试(数据驱动测试)
    bool IsPrime (int n ) { ... } -1 0 1 2 13 99 ...
  • 36. GTest - 参数化测试
    • 可能,我们会这样写:
    TEST(IsPrimeTest, TestAll) { EXPECT_FALSE( IsPrime(-1) ); EXPECT_FALSE( IsPrime(0) ); EXPECT_FALSE( IsPrime(1) ); EXPECT_TRUE( IsPrime(2) ); EXPECT_TRUE( IsPrime(13) ); ... }
  • 37. GTest - 参数化测试 分享: 一个测试案例,理想情况下,只需要一个断言。
  • 38. GTest - 参数化测试
    • 这就是理想情况:
    • TEST_P (IsPrimeParamTest, TrueReturn)
    • {
    • int n = GetParam();
    • EXPECT_TRUE (IsPrime(n));
    • }
  • 39. GTest - 参数化测试
    • class IsPrimeParamTest : public::testing:: TestWithParam<int>
    • {
    • }
    • INSTANTIATE_TEST_CASE_P (TrueReturn, IsPrimeParamTest, testing::Values( 2,13,17,23 ));
  • 40. GTest - 运行参数
    • 系统环境变量
    • 命令行参数
      • --gtest_filter = *.*
    • 代码中指定 FLAG
      • testing::GTEST_FLAG(output) = &quot;xml:&quot;;
  • 41. 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
  • 42. 小技巧
  • 43. 小技巧
    • 获取当前测试案例名称:
    • 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() );
  • 44. GTest
    • GTest 就讲到这里,
    • 下面说说我对测试开发的一些理解
  • 45. 经验交流
    • 分享:做 有用 的测试
    最高原则
  • 46. 经验交流
    • 分享:
    • 测试案例执行的次数越多,价值越大!
  • 47. 经验交流
    • 分享:
    • 稳定的测试案例才有效
  • 48. 经验交流
    • 正确理解 Mock:
      • Dummy Object
      • Test Stub
      • Test Spy
      • Mock Object
      • Fake Object
  • 49. Google Mock
    • TEST(PainterTest, CanDrawSomething) {
    • MockTurtle turtle;
    • EXPECT_CALL(turtle, PenDown())
    • .Times(AtLeast(1));
    • Painter painter(&turtle);
    • EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
    • }
  • 50. 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. 故事模板 场景模板
  • 51. 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;
  • 52. 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);
    • }
    • }
  • 53. 我的实践
    • 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()));
    • }
  • 54. 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
  • 55. Principles
    • Minimize Untestable Code
    • Keep Test Logic Out of Production Code
    • Verify One Condition per Test
    • Test Conerns Separtely
    • Ensure Commensurate Effort and Responsibility
  • 56. 做有用的测试! 谢谢大家

×