当当中的断言战败时,怎么测量检验异步函数

4. 测试私有属性和私有方法使用反射机制

 3.Shuffling the Tests洗牌测试

您可以指定–gtest_shuffle标志(或将GTEST_SHUFFLE环境变量设置为1),以便以随机顺序在程序中运行测试。
这有助于揭示测试之间的依赖关系。

默认情况下,Google测试使用根据当前时间计算的随机种子。
因此,你每次都会得到不同的顺序。
控制台输出包括随机种子值,以便以后可以重现与顺序相关的测试失败。
要明确指定随机种子,请使用–gtest_random_seed =
SEED标志(或设置GTEST_RANDOM_SEED环境变量),其中SEED是介于0和99999之间的整数。种子值0是特殊的:它告诉Google
Test执行默认行为 从当前时间计算种子。

如果将此与–gtest_repeat =
N结合使用,Google测试会选择不同的随机种子,并在每次迭代中重新洗牌测试。

  1. 测试框架 mocha
  2. 断言库:should.js、expect.js、chai
  3. 覆盖率:istanbul、jscover、blanket
  4. Mock库:muk
  5. 测试私有方法:rewire
  6. Web测试:supertest
  7. 持续集成:Travis-cli
assertThat($result, $this->logicalOr, $this->isInstanceOf; } public function additionProviderGetLatestUpdateAppApi() { return [ 'apple' => [1], 'android' => [2], 'null' => [9999] ]; } }

1.4检查当前测试中的故障

  :: test :: Test类中的HasFatalFailure():
如果当前测试中的断言遭遇致命故障,则返回true。
这允许函数捕获子例程中的致命故障并及早返回。

class Test {
 public:
  ...
  static bool HasFatalFailure();
};

 典型的用法,基本上模拟抛出的异常的行为是:

TEST(FooTest, Bar) {  
    Subroutine();  // Aborts if Subroutine() had a fatal failure. 
   if (HasFatalFailure())    
     return;  
   // The following won't be executed. 
   ...
}

HasFatalFailure如果在TEST(),TEST_F()或测试夹具之外使用,则必须添加::
testing :: Test ::前缀,如: 

if (::testing::Test::HasFatalFailure())
  return;

类似的,HasNonfatalFailure():如果当前测试至少有一个非致命失败,返回true。

HasFailure() :如果当前测试至少有一个失败,返回true。

  • lib,存放模块代码的地方
  • test,存放单元测试代码的地方
  • index.js,向外导出模块的地方
  • package.json,包描述文件

2. 断言方法

四、Global Set-Up and Tear-Down

正如你可以在测试级别和测试用例级别设置和拆卸,您也可以在测试程序级别执行。

首先,你要继承:: testing :: Environment类来定义一个测试环境:

class Environment {
 public:
  virtual ~Environment() {}
  // Override this to define how to set up the environment.
  virtual void SetUp() {}
  // Override this to define how to tear down the environment.
  virtual void TearDown() {}
};

然后,通过调用:: testing :: Add Global Test
Environment()函数,注册我们的环境类的实例:

Environment* AddGlobalTestEnvironment(Environment* env);

现在,当调用RUN_ALL_TESTS()时,它首先调用环境对象的SetUp()方法,然后如果没有致命失败则运行测试,最后调用环境对象的TearDown()。

注册多个环境对象是可以的。
在这种情况下,他们的SetUp()将按照它们注册的顺序被调用,并且它们的TearDown()将以相反的顺序被调用。

请注意,Google测试会对注册的环境对象拥有所有权。
因此,不要自己删除它们。

您应该在调用RUN_ALL_TESTS()之前调用AddGlobalTestEnvironment(),可能在main()中调用。
如果你使用gtest_main,你需要在main()启动之前调用它才能生效。
一种方法是定义一个全局变量,如下所示:

::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new FooEnvironment); 

但是,我们强烈建议您编写自己的main()并调用AddGlobalTestEnvironment(),因为依赖于全局变量的初始化使代码更难读取,并且可能会导致问题,当您从不同的转换单元注册多个环境,
它们之间的依赖性(记住编译器不保证来自不同转换单元的全局变量的初始化顺序)。

var fs = require;var muk = require;before(function () { muk(fs, 'readFile', function(path, encoding, callback) { process.nextTick(function () { callback(new Error("mock readFile error")); }); });});// it();after(function () { muk.restore;

测试私有属性可使用ReflectionClass(), 获取属性用getProperty(),
设置属性的值用setValue(), 获取方法用getMethod(),
设置属性和方法可被访问使用setAccessible。例如检测白名单路径。

一、在子程序中使用断言(Using Assertions in Sub-routines)

1.1 将跟踪添加到断言

如果从几个地方调用测试子程序,当其中的断言失败时,可能很难判断失败来自哪个子程序的调用。
您可以使用额外的日志或自定义失败消息缓解这个问题,但通常会堵塞您的测试。
更好的解决方案是使用SCOPED_TRACE宏:

SCOPED_TRACE(message);

messsage可以是任何可以流入std::ostream的东西。此宏会将当前文件名、行号和给定消息添加到每个失败消息中。 当控件离开当前词法作用域时,效果将被撤消。

For example,

 void Sub1(int n) {
   EXPECT_EQ(1, Bar(n));
   EXPECT_EQ(2, Bar(n + 1));
 }

 TEST(FooTest, Bar) {
   {
     SCOPED_TRACE("A");  // This trace point will be included in
                         // every failure in this scope.
     Sub1(1);
   }//到这SCOPED_TRACE的作用域就结束。
   // Now it won't.
   Sub1(9);//都调用了子程序Sub1
 }

可能会导致这样的消息:

path/to/foo_test.cc:11: Failure
Value of: Bar(n)
Expected: 1
  Actual: 2
   Trace:
path/to/foo_test.cc:17: A

path/to/foo_test.cc:12: Failure
Value of: Bar(n + 1)
Expected: 2
  Actual: 3

没有跟踪,很难知道两个失败分别来自哪个Sub1()的调用。
(你可以在Sub1()中为每个断言添加一个额外的消息,以指示n的值,但这很乏味。)

关于使用SCOPED_TRACE的一些提示:

没有跟踪,很难知道两个失败分别来自哪个Sub1()的调用。
(你可以在Sub1()中为每个断言添加一个额外的消息,以指示n的值,但这很乏味。)

关于使用SCOPED_TRACE的一些提示:

  • 使用合适的消息,通常足以在子例程的开头使用SCOPED_TRACE,而不是在每个调用站点。
  • 当调用循环内的子例程时,使循环迭代器成为SCOPED_TRACE中的消息的一部分,以便您可以知道失败来自哪个迭代。
  • 有时,跟踪点的行号足以识别子例程的特定调用。在这种情况下,您不必为SCOPED_TRACE选择唯一的消息。你可以简单地使用“”。
  • 当外部作用域中有一个SCOPED_TRACE时,可以在内部作用域中使用SCOPED_TRACE。在这种情况下,所有活动跟踪点将按照遇到的相反顺序包含在失败消息中。
  • 跟踪转储是可以在Emacs的编译缓冲区中点击 –
    命中返回行号,你会被带到源文件中的那一行!

Travis-cli还会对项目颁发标签,

常用有assertTrue, assertNull, assertThat()。

三、在同一测试用例中的测试之间共享资源

Google
Test为每个测试创建一个新的测试夹具对象,以使测试独立,更容易调试。
然而,有时测试使用昂贵的资源设置,使得单拷贝测试模型过于昂贵。

如果测试不更改资源,则它们在共享单个资源副本中没有任何危害。
因此,除了每次测试的set-up/tear-down,Google测试还支持每个测试用例的set-up/tear-down。
使用它:

  • 在你的测试夹具类(比如FooTest)中,定义一些成员变量来保存共享资源。
  • 在同一个测试夹具类中,定义一个静态void
    SetUpTestCase()函数(记住不要拼写它作为一个小u的SetupTestCase)来设置共享资源和静态void
    TearDownTestCase()函数来删除它们。

OK!
在运行FooTest测试用例中的第一个测试(即在创建第一个FooTest对象之前)之前,Google
Test自动调用SetUpTestCase(),并在运行最后一个测试之后(即删除最后一个FooTest对象后)调用TearDownTestCase()。
在其间,测试可以使用共享资源。

记住测试顺序是未定义的,所以你的代码不能依赖于另一个之前或之后的测试。
此外,测试必须不能修改任何共享资源的状态,或者,如果它们修改状态,则它们必须在将控制传递给下一个测试之前将状态恢复到其原始值。

Here’s an example of per-test-case set-up and tear-down:

class FooTest : public ::testing::Test {
 protected:
  // Per-test-case set-up.
  // Called before the first test in this test case.
  // Can be omitted if not needed.
  static void SetUpTestCase() {
    shared_resource_ = new ...;
  }

  // Per-test-case tear-down.
  // Called after the last test in this test case.
  // Can be omitted if not needed.
  static void TearDownTestCase() {
    delete shared_resource_;
    shared_resource_ = NULL;
  }

  // You can define per-test set-up and tear-down logic as usual.
  virtual void SetUp() { ... }
  virtual void TearDown() { ... }

  // Some expensive resource shared by all tests.
  static T* shared_resource_;
};

T* FooTest::shared_resource_ = NULL;

TEST_F(FooTest, Test1) {
  ... you can refer to shared_resource here ...
}
TEST_F(FooTest, Test2) {
  ... you can refer to shared_resource here ...
}

使用–coverage-html导出的报告含有类与特质覆盖率、行覆盖率、函数与方法覆盖率。可查看当前单元测试覆盖的范围。例如输出WebDefenderTest的代码覆盖率到桌面(phpunit
tests/unit/WebDefenderTest –coverage-html ~/Desktop/test)

 5.2 禁用捕获测试 – 抛出异常Disabling Catching Test-Thrown Exceptions

   Google测试可以在启用或不启用exception的情况下使用。如果测试抛出C
++异常或(在Windows上)结构化异常(SEH),默认情况下Google测试会捕获它,将其报告为测试失败,并继续执行下一个测试方法。这将最大化测试运行的覆盖率。此外,在Windows上,未捕获的异常将导致弹出窗口,因此捕获异常允许您自动运行测试。

 
然而,当调试测试失败时,您可能希望异常由调试器处理,以便您可以在抛出异常时检查调用堆栈。要实现此目的,请在运行测试时将GTEST_CATCH_EXCEPTIONS环境变量设置为0,或使用–gtest_catch_exceptions
= 0标志。

在开发Web项目的时候,要测试某一个API,如:/user,到底怎么编写测试用例呢?

getPathInfo; if (!$path || !$this->pathWhiteList || !is_array) { return false; } foreach ($this->pathWhiteList as $item) { if (preg_match { return true; } } return false; } }

getProperty; $reflectedPathWhiteList->setAccessible; $reflectedPathWhiteList->setValue($webDefenderService, $pathProperty); $reflectedRequest = $reflectedClass->getProperty; $reflectedRequest->setAccessible; $reflectedRequest->setValue; $reflectedMethod = $reflectedClass->getMethod; $reflectedMethod->setAccessible; $this->assertEquals($result, $reflectedMethod->invoke; } public function additionProviderPathWhiteList() { $allPath = ['.*']; $checkPath = ['^auth/']; $authSendSmsRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/auth/sendSms']); $indexRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/']); $noMatchRequest = new Request([], [], [], [], [], ['HTTP_HOST' => 'api.dev.com', 'REQUEST_URI' => '/product/sendSms']); return [ 'index' => [[], $authSendSmsRequest, false], 'no request' => [$allPath, $indexRequest, false], 'all request' => [$allPath, $authSendSmsRequest, true], 'check auth sms' => [$checkPath, $authSendSmsRequest, true], 'check path no match' => [$checkPath, $noMatchRequest, false] ]; } }

九、Catching Failures

如果您要在Google测试之上构建测试实用程序,则需要测试您的实用程序。
你将使用什么框架来测试它? Google测试,当然。

挑战是验证您的测试实用程序是否正确报告故障。
在框架中通过抛出异常报告失败,您可以捕获异常并断言。 但是Google
Test不会使用异常,那么我们如何测试一段代码是否会产生预期的失败呢?

“gtest / gtest-spi.h”包含一些构造来做到这一点。 #include
它,然后可以使用

EXPECT_FATAL_FAILURE(statement, substring);​

to assert that statement generates a fatal (e.g. ASSERT_*) failure
whose message contains the given substring, or use

EXPECT_NONFATAL_FAILURE(statement, substring);​

if you are expecting a non-fatal (e.g. EXPECT_*) failure.

。。。。。//需要时再看

单元测试准则

     ./tests/Unit   ./tests/Feature     ./app/Services ./app/Facades/Services/WebDefenderService.php                

5.控制如何报告失败

Mocha的超时设定默认是2s,如果执行的测试超过2s的话,就会报timeout错误。可以主动修改超时时间,有两种方法。

5. 代码覆盖率

 5.3 让另一个测试框架驱动

   
如果您使用的项目已经使用了另一个测试框架,但尚未准备好完全切换到Google测试,则可以通过在现有测试中使用其断言来获得Google测试的许多优势。
只是改变你的main()函数看起来像:

#include "gtest/gtest.h"

int main(int argc, char** argv) {
  ::testing::GTEST_FLAG(throw_on_failure) = true;
  // Important: Google Test must be initialized.
  ::testing::InitGoogleTest(&argc, argv);

  ... whatever your existing testing framework requires ...
}

 这样,除了你的框架提供的断言之外,您还可以使用Google Test断言,例如:

void TestFooDoesBar() {
  Foo foo;
  EXPECT_LE(foo.Bar(1), 100);     // A Google Test assertion.
  CPPUNIT_ASSERT(foo.IsEmpty());  // A native assertion.
}

。。。。。后边的省略了,这个应该需要不到

模块具备limit方法,输入一个数值,小于0的时候返回0,其余正常返回

expectExceptionCode; Cache::put('device-login-error-account-', '1,2,3,4,5', 300); UserSecurityService::$request = null; UserSecurityService::$udid = null; UserSecurityService::deviceCheck; } }

 5.1 将断言失败转换为断点

 
当在调试器下运行测试程序时,如果调试器可以捕获断言故障并自动进入交互模式,则非常方便。
Google测试的break-on-failure 模式支持此行为。

 
要启用它,请将GTEST_BREAK_ON_FAILURE环境变量设置为0以外的值。或者,您可以使用–gtest_break_on_failure命令行标志。

可用性:Linux,Windows,Mac。

JerryC% istanbul cover _mocha module limit ✓ limit should success async ✓ async getContent ✓ getContent add ✓ add should #Promise ✓ should.reject ✓ should fulfilled 6 passing ================== Coverage summary ======================Statements : 100% Branches : 100% Functions : 100% Lines : 100% ==========================================================

assertThat、isTrue、isInstanceOf、logicalAnd()。例如检测返回的结果是否是null或ApiApp类。

十 一、运行测试程序:高级选项

Google
Test测试程序是普通的可执行文件。 一旦构建,您可以直接运行它们,并通过以下环境变量 命令行标志影响其行为。 要使标志工作,您的程序必须在调用RUN_ALL_TESTS()之前调用::
testing :: InitGoogleTest()。

要查看支持的标志及其用法的列表,请使用–help标志运行测试程序。 您也可以使用-h,

  • ?或/? 简称。 此功能在版本1.3.0中添加。
    设置标志的三种方式:以–gtest_filter 为例       
    1)命令行运行程序时直接加上参数:./foo_test
    –gtest_filter=QueueTest.*;       2)在代码中设置::: testing ::
    GTEST_FLAG(filter)= “QueueTest.*” **注意没有前边的–gtest_。      
    3)testing::FLAGS_gtest_filter = “QueueTest.*”; 如果选项由环境变量和标志指定,则后者优先。 大多数选项也可以在代码中设置/读取:访问命令行标志的值–gtest_foo,write ::
    testing :: GTEST_FLAG(foo)
    。  **注意标志是:–gtest_foo
    ; 在代码中调用是:: testing ::
    GTEST_FLAG(foo);没有前边的**
    –gtest_。** 一个常见的模式是在调用:: testing ::
    InitGoogleTest()之前设置标志的值:

    int main(int argc, char** argv) {

    // Disables elapsed time by default.
    ::testing::GTEST_FLAG(print_time) = false;
    
    // This allows the user to override the flag on the command line.
    ::testing::InitGoogleTest(&argc, argv);
    
    return RUN_ALL_TESTS();
    

    }

上面的代码只是运行了代码,并没有对结果进行检查,这时候就要用到断言库了,Node.js中常用的断言库有:

7. 参考文档

1. 选择测试

   此部分显示用于选择哪些测试运行的各种选项。

 1.1 列出测试名称
 
有时,在运行程序之前,必须列出程序中的可用测试,以便在需要时应用过滤器。
包括标志–gtest_list_tests覆盖所有其他标志,并列出以下格式的测试:

TestCase1.
  TestName1
  TestName2
TestCase2.
  TestName

如果提供了标志,则列出的所有测试都不会真正运行。
此标志没有相应的环境变量。

  1.2运行测试的子集

默认情况下,Google测试程序运行用户定义的所有测试。
有时,您只想运行测试的一个子集(例如,用于调试或快速验证更改)。
如果将GTEST_FILTER环境变量或–gtest_filter标志设置为过滤器字符串,则Google
Test将仅运行其全名(以TestCaseName.TestName的形式)与过滤器匹配的测试。

过滤器的格式是通配符模式(称为正模式)的’:’分隔的列表,可选地后跟一个“

  • ”和另一个“:”分隔的模式列表(称为负模式)。
    测试匹配过滤器当且仅当它与任何正模式匹配但不匹配任何负模式时。

模式可能包含“*”(匹配任何字符串)或’?’ (匹配任何单个字符)。
为了方便,过滤器’* -NegativePatterns’也可以写为’-NegativePatterns’。

For example:

  • ./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.

图片 1

 1.3 暂时禁用测试

如果你有一个失败的测试,无法立即修复,可以在其名称中添加DISABLED_前缀。
将排除它执行。 这比注释掉代码或使用#if
0更好,因为禁用的测试仍然编译(因此不会rot)。

如果你需要禁用测试用例中的所有测试,可以在每个测试名称的前面添加DISABLED_,或者将其添加到测试用例名称的前面。

例如,以下测试不会由Google Test运行,即使它们仍然将被编译:

// 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) { ... } 

注意:此功能只能用于临时缓解。 您仍然必须在以后修复已禁用的测试。
提醒您,如果测试计划包含任何已停用的测试,Google测试会打印一条横幅警告您。

提示:您可以轻松计算已使用grep禁用的测试的数量。
此数字可用作提高测试质量的指标。

1.4 暂时启用禁用测试

要在测试执行中包括禁用的测试,只需使用–gtest_also_run_disabled_tests标志调用测试程序或将GTEST_ALSO_RUN_DISABLED_TESTS环境变量设置为0以外的值。您可以将此与–gtest_filter标志结合,以进一步选择要运行哪些已禁用的测试

代码中设置如下:前边加FLAGS_ (好坑啊,文档里也没说,我查出来的)。

testing::FLAGS_gtest_also_run_disabled_tests = 2;

这个指标就叫做”代码覆盖率”(code coverage)。它有四个测量维度。

6. 指定代码覆盖率报告要包含哪些文件

八、测试private修饰的代码

如果您更改软件的内部实现,只要用户不能观察到这种变化,您的测试就不会中断。
因此,根据黑盒测试原则,大多数时候你应该通过其公共接口测试你的代码。

如果你仍然发现自己需要测试内部实现代码,考虑是否有一个更好的设计,不需要你这样做。
如果你必须测试非公共接口代码。 有两种情况需要考虑:

  •  静态函数(不同于静态成员函数!)或未命名的命名空间
  •  私人或受保护的类成员

使用should提供的Promise断言接口:

appUpdateData(); $this->assertTrue(count(array_intersect_assoc == count; } public function addProviderAppUpdateData() { return [ 'null' => [null, ['status' => 0, 'isIOS' => false, 'latest_version' => 'V']], 'error app id' => ['sdas123123', ['status' => 0, 'isIOS' => false, 'latest_version' => 'V']], 'android force update' => ['bx7_3.3.5_120', ['status' => 0, 'isIOS' => false]], 'ios force update' => ['apple_3.3.2_117', ['status' => 1, 'isIOS' => true]], 'android soft update' => ['sanxing_3.3.2_117', ['status' => 2, 'isIOS' => false]], 'ios soft update' => ['apple_3.3.3_118', ['status' => 2, 'isIOS' => true]], 'android normal' => ['fhqd_3.3.6_121', ['status' => 1, 'isIOS' => false]], 'ios normal' => ['apple_3.3.5_120', ['status' => 1, 'isIOS' => true]], 'h5' => ['h5_3.3.3', ['status' => 1, 'isIOS' => false]] ]; } }

 4.控制测试输出

 本节教导如何调整测试结果的报告方式。

language: node_jsnode_js: - "0.12"

在配置文件里设置whitelist中的processUncoveredFilesFromWhitelist=true,
设置目录用标签,设置文件用标签。例如指定app/Services目录下的所有文件和app/Facades/Services/WebDefenderService.php在报告中。

Google C++单元测试框架GoogleTest—AdvancedGuide(译文)下,advancediqtest

因为AdvancedGuide文档太长,分上下两部分,本文档接googletest–AdvancedGuide(译文)上:Google
C++单元测试框架GoogleTest—AdvancedGuide(译文)上。

使用:supertest

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

默认情况下,Google测试会打印运行每个测试所需的时间。为了抑制这种情况,使用–gtest_print_time

0命令行标志运行测试程序。将GTEST_PRINT_TIME环境变量设置为0具有相同的效果。

可用性:Linux,Windows,Mac。 (在Google Test
1.3.0及更低版本中,默认行为是不打印已用时间。)

这条命令同时还生成了一个 coverage 子目录,其中的 coverage.json
文件包含覆盖率的原始数据,coverage/lcov-report
是可以在浏览器打开的覆盖率报告,其中有详细信息,到底哪些代码没有覆盖到。

用来提供参数和结果,使用 @dataProvider
标注来指定使用哪个数据供给器方法。例如检测app升级数据是否符合预期,addProviderAppUpdateData()提供测试的参数和结果。testAppUpdateData返回的结果是否和给定的预期结果相等,即如果$appId='apple_3.3.2_117',
$result=['status' => 0, 'isIOS' => false],
则$data中如果含有['status' => 0, 'isIOS' => false],
则断言成功。建议在数据提供器,逐个用字符串键名对其命名,这样在断言失败的时候将输出失败的名称,更容易定位问题

 五、值参数化测试

//这个功能挺复杂,专门写在一个单独的文档解析:

 

var express = require("express");var request = require("supertest");var app = express();// 定义路由app.get('/user', function{ res.send(200, { name: 'jerryc' });});describe('GET /user', function(){ it('respond with json', function{ request .get .set('Accept', 'application/json') .expect('Content-Type', /json/) .expect .end(function  { if { done; } res.body.name.should.be.eql; done;});

使用expectExceptionCode()对错误码进行检测,不建议对错误信息文案进行检测。例如检测设备被锁后是否抛出3026错误码。

1.3在子程序中的断言(Asserting on Subroutines)

如上所示,如果你的测试调用了一个有ASSERT_
*失败的子程序,测试将在子程序返回后继续。 这可能不是你想要的。

通常人们希望致命的失败传播像异常一样。 为此,Google测试提供以下宏:

Fatal assertion Nonfatal assertion Verifies
ASSERT_NO_FATAL_FAILURE(statement); EXPECT_NO_FATAL_FAILURE(statement); statement doesn’t generate any new fatal failures in the current thread.

仅检查执行断言的线程中的失败,以确定这种类型的断言的结果。
如果语句创建新线程,这些线程中的失败将被忽略。

例如:

ASSERT_NO_FATAL_FAILURE(Foo());

int i;
EXPECT_NO_FATAL_FAILURE({
  i = Bar();
}); 
describe('async', function () { it('async', function  { lib.async(function  { done;});

1. 数据供给器

七、类型参数化测试

在不知道类型参数的情况下编写测试— 这就是“类型参数化测试”。

类型参数化测试类似于类型测试,除了它们不需要预知类型列表。
相反,您可以首先定义测试逻辑,然后使用不同类型列表实例化它。
你甚至可以在同一个程序中多次实例化它。

如果您正在设计一个接口或概念,则可以定义一组类型参数化测试,以验证接口/概念的任何有效实现应具有的属性。
然后,每个实现的作者可以使用他的类型来实例化测试套件,以验证它符合需求,而不必重复地编写类似的测试。
这里有一个例子:

1. 定义一个fixture类模板,就像我们用类型测试一样:

First, define a fixture class template, as we did with typed tests:

template <typename T>
class FooTest : public ::testing::Test {
  ...
};

2. 声明你要定义的类型参数化测试用例:

TYPED_TEST_CASE_P(FooTest);

这个后缀P代表参数化或模式,随你怎么想。

  1. 使用TYPED_TEST_P()来定义类型参数化测试。您可以根据需要重复多次:

    TYPED_TEST_P(FooTest, DoesBlah) {
    // Inside a test, refer to TypeParam to get the type parameter.
    TypeParam n = 0;

    }

    TYPED_TEST_P(FooTest, HasPropertyA) { … }

现在棘手的部分:您需要使用REGISTER_TYPED_TEST_CASE_P宏注册所有测试模式,然后才能实例化它们。

宏的第一个参数是测试用例名称; 其余的是在这个测试用例中的测试的名称

REGISTER_TYPED_TEST_CASE_P(FooTest,
                           DoesBlah, HasPropertyA);

最后,你可以用你想要的类型来实例化模式。
如果你把上面的代码放在头文件中,你可以在多个C
++源文件#include它,并实例化多次。

typedef ::testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);

为了区分模式的不同实例,INSTANTIATE_TYPED_TEST_CASE_P宏的第一个参数是将添加到实际测试用例名称中的前缀。 请记住为不同实例选择唯一前缀

在类型列表只包含一个类型的特殊情况下,您可以直接编写该类型,而不使用::
testing :: Types <…>,如下所示:

INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);

ou can see samples/sample6_unittest.cc for a complete example.

**类型测试与类型参数化的区别:

1. 类型测试是你知道所有的类型,把所有类型注册,实例化测试。

2.
类型参数化是你是接口的定义者,知道每个接口函数的基本功能,而它的具体实现可以在将来被
  人实现,你可以提前定义好测试用例,然后把所有的测试注册。

$ istanbul cover _mocha -- tests/test.sqrt.js -R spec

PHPUnit官方文档

 1. 静态函数

未命名的命名空间中的静态函数和定义/声明仅在同一转变单元中可见。要测试它们,您可以在你的*
_test.cc文件中include 要测试的整个.cc文件。 (#include
.cc文件不是重用代码的好方法 – 你不应该在生产代码中这样做!)

然而,更好的方法是将私有代码移动到foo ::
internal命名空间中,其中foo是你项目通常使用的命名空间,并将私有声明放在*
-internal.h文件中。允许您的生产.cc文件和测试包括此内部标头,但是您的客户端不包括。这样,您可以完全测试您的内部实现,而不会泄漏到您的客户端。

  • 行覆盖率(line coverage):是否每一行都执行了?
  • 函数覆盖率(function coverage):是否每个函数都调用了?
  • 分支覆盖率(branch coverage):是否每个if代码块都执行了?
  • 语句覆盖率(statement coverage):是否每个语句都执行了?

3. 对异常进行测试

 六、类型测试

假设您有一个接口的多个实现,并希望确保所有这些都满足一些常见的要求。
或者,您可能定义了几个类型,它们应该符合相同的“概念”,并且您想要验证它。
在这两种情况下,您都希望为不同类型重复相同的测试逻辑。 

 虽然你可以为你想测试的每个类型写一个TEST或TEST_F(你甚至可以把测试逻辑放入你从TEST调用的函数模板),它是乏味的,不缩放:如果你想要m个测试
n类型,你最终会写m * n TESTs。

类型测试允许您在类型列表上重复相同的测试逻辑。
你只需要写一次测试逻辑,虽然在写类型测试时你必须知道类型列表。
以下是您的操作方法:

1. 定义一个fixture类模板。 它应该由一个类型参数化。 记住继承:: testing
:: Test:

template <typename T>
class FooTest : public ::testing::Test {
 public:
  ...
  typedef std::list<T> List;
  static T shared_;
  T value_;
};

2. 将类型列表与测试用例相关联,这将针对列表中的每个类型重复:

typedef ::testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_CASE(FooTest, MyTypes);

typedef对于TYPED_TEST_CASE宏正确解析是必要的。
否则编译器会认为类型列表中的每个逗号引入一个新的宏参数。

3. 使用TYPED_TEST()而不是TEST_F()为此测试用例定义一个类型测试。
您可以根据需要重复此操作次数:

TYPED_TEST(FooTest, DoesBlah) {
  // Inside a test, refer to the special name TypeParam to get the type
  // parameter.  Since we are inside a derived class template, C++ requires
  // us to visit the members of FooTest via 'this'.
  TypeParam n = this->value_;

  // To visit static members of the fixture, add the 'TestFixture::'
  // prefix.
  n += TestFixture::shared_;

  // To refer to typedefs in the fixture, add the 'typename TestFixture::'
  // prefix.  The 'typename' is required to satisfy the compiler.
  typename TestFixture::List values;
  values.push_back(n);
  ...
}

TYPED_TEST(FooTest, HasPropertyA) { ... }

You can see samples/sample6_unittest.cc for a complete example.

在当前目录下执行mocha

namespace AppFacadesServices; /** * Class WebDefender */ class WebDefenderService extends BaseService { //ip白名单 private $ipWhiteList = [ '10.*', '172.18.*', '127.0.0.1' ]; /** * ip是否在白名单中 * * @param string $ip * * @return bool */ private function checkIPWhiteList { if (!$this->ipWhiteList || !is_array { return false; } foreach ($this->ipWhiteList as $item) { if (preg_match { return true; } } return false; } }

setAccessible; $this->assertEquals($result, $checkIPWhiteList->invokeArgs(new WebDefenderService; } public function additionProviderIp() { return [ '10 ip' => ['10.1.1.7', true], '172 ip' => ['172.18.2.5', true], '127 ip' => ['127.0.0.1', true], '192 ip' => ['192.168.0.1', false] ]; } }

2. 私有类成员

私人class成员只能从班class或友元类那里接触。要访问类的私有成员,可以将测试夹具声明为类的朋友,并在夹具中定义访问器。使用夹具的测试,可以通过夹具中的访问器访问您的生产类的私有成员。注意,即使你的夹具是你的生产类的朋友,你的测试不是它的友元类,因为他们技术上是定义在夹具的子类中。

另一种测试私有成员的方法是将它们重构为一个实现类,然后在*
-internal.h文件中声明它。您的客户端不允许包括此标题,但您的测试可以。这种称为Pimpl(私有实现)习语。

或者,您可以通过在类主体中添加以下行,将个别测试声明为class的友元类:

FRIEND_TEST(TestCaseName, TestName);

  For example,

// foo.h
#include "gtest/gtest_prod.h"

// Defines FRIEND_TEST.
class Foo {
  ...
 private:
  FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
  int Bar(void* x);
};

// foo_test.cc
...
TEST(FooTest, BarReturnsZeroOnNull) {
  Foo foo;
  EXPECT_EQ(0, foo.Bar(NULL));
  // Uses Foo's private member Bar().
}

当你的类在命名空间中定义时,需要特别注意,因为你应该在同一个命名空间中定义你的测试夹具和测试,如果你想他们是你的class的友元。
例如,如果要测试的代码如下所示:

namespace my_namespace {

class Foo {
  friend class FooTest;
  FRIEND_TEST(FooTest, Bar);
  FRIEND_TEST(FooTest, Baz);
  ...
  definition of the class Foo
  ...
};

}  // namespace my_namespace

Your test code should be something like:

namespace my_namespace {
class FooTest : public ::testing::Test {
 protected:
  ...
};

TEST_F(FooTest, Bar) { ... }
TEST_F(FooTest, Baz) { ... }

}  // namespace my_namespace
  • finally | eventually
  • fulfilled
  • fulfilledWith
  • rejected
  • rejectedWith
  • then

如果只测试私有方法可使用ReflectionMethod()反射方法,使用setAccessible设置方法可访问,并使用invokeArgs调用方法。例如检测IP是否在白名单中。

十、Getting the Current Test’s Name

   有时一个函数可能需要知道当前运行的测试的名称。
例如,您可以使用测试夹具的SetUp()方法根据正在运行的测试设置黄金文件名。
:: testing :: TestInfo类具有以下信息:

namespace testing {

class TestInfo {
 public:
  // Returns the test case name and the test name, respectively.
  //
  // Do NOT delete or free the return value - it's managed by the
  // TestInfo class.
  const char* test_case_name() const;
  const char* name() const;
};

}  // namespace testing

To obtain a TestInfo object for the currently running test,
call current_test_info() on the UnitTest singleton object:

// Gets information about the currently running test.
// Do NOT delete the returned object - it's managed by the UnitTest class.
const ::testing::TestInfo* const test_info =
  ::testing::UnitTest::GetInstance()->current_test_info();
printf("We are in test %s of test case %s.n",
       test_info->name(), test_info->test_case_name());

如果没有运行测试,current_test_info()返回一个空指针。
特别是,你不能在TestCaseSetUp(),TestCaseTearDown()中找到测试用例名称(在那里你知道测试用例名称),或者从它们调用的函数。

istanbul cover _mocha

 4.2 抑制所用时间

需求变更啦:
limit这个方法还要求返回值大于100时返回100。针对需求重构代码之后,正是测试用例的价值所在了,它能确保你的改动对原有成果没有造成破坏。但是,你要多做的一些工作的是,需要为新的需求编写新的测试代码。

1.2 传播致命失败

使用ASSERT_ *和FAIL
*时的常见陷阱认为当它们失败时,它们会中止整个测试。
例如,以下测试将会导致错误:

void Subroutine() {
  // Generates a fatal failure and aborts the current function.
  ASSERT_EQ(1, 2);//失败时只是终止当前函数
  // The following won't be executed.
  ...
}

TEST(FooTest, Bar) {
  Subroutine();
  // The intended behavior is for the fatal failure
  // in Subroutine() to abort the entire test.
  // The actual behavior: the function goes on after Subroutine() returns.
  //  实际行为:函数在Subroutine()返回后继续。
  int* p = NULL;
  *p = 3; // Segfault!产生一个错误
} 

由于我们不使用异常,因此在技术上不可能在这里实现预期的行为。
为了减轻这种情况,Google测试提供了两种解决方案。 您可以使用(ASSERT |
EXPECT)_NO_FATAL_FAILURE断言或HasFatalFailure()函数。
它们在以下两个小节中描述。

实施单元测试的时候, 如果没有一份经过实践证明的详细规范, 很难掌握测试的
“度”, 范围太小施展不开, 太大又侵犯 “别人的” 地盘. 上帝的归上帝,
凯撒的归凯撒, 给单元测试念念紧箍咒不见得是件坏事,
反而更有利于发挥单元测试的威力,
为代码重构和提高代码质量提供动力.这份文档来自 Geotechnical,
是一份非常难得的经验准则. 你完全可以以这份准则作为模板,
结合所在团队的经验, 整理出一份内部单元测试准则.

6. 将测试功能分发到多台机器

如果您有多个机器可以用来运行测试程序,您可能希望并行运行测试功能并更快地获得结果。我们称之为技术分片,其中每台机器被称为分片。

Google测试与测试分片兼容。要利用此功能,您的测试运行器(不是Google测试的一部分)需要执行以下操作:

您的项目可能有没有Google
Test的测试,因此不了解此协议。为了让测试运行器确定哪个测试支持分片,它可以将环境变量GTEST_SHARD_STATUS_FILE设置为不存在的文件路径。如果测试程序支持分片,它将创建此文件以确认事实(文件的实际内容此时不重要;虽然我们将来可能会在其中粘贴一些有用的信息。否则它不会创建它。

这里有一个例子来说明。假设您有一个包含以下5个测试函数的测试程序foo_test:

TEST(A, V)
TEST(A, W)
TEST(B, X)
TEST(B, Y)
TEST(B, Z)

你有3台机器在您的处置。
要并行运行测试功能,您需要在所有机器上将GTEST_TOTAL_SHARDS设置为3,并将GTEST_SHARD_INDEX分别设置为0,1和2。
然后你将在每台机器上运行相同的foo_test。

Google测试有权更改工作在分片上的分布情况,但这里有一种可能的情况:

  • Machine #0 runs A.V and B.X.
  • Machine #1 runs A.W and B.Y.
  • Machine #2 runs B.Z.

「Github」MZMonster :@MZMonster JC_Huang :@JerryC8080

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图