gtest和gmock的关系_gtest教程

gtest和gmock的关系_gtest教程对于c++来说写单元测试和mock框架不是一件容易的事情。还好,Google为我们搭建了一个出色的单元测试和mock框架。网上的例子很多都过多强调概念,本文用一个简单的例子让大家对于什么是gtest和gmock让大家有一个直观的了解,让大家很快上手,就像写helloword一样容易。gtest&gmock的1.6版本的使用make编译,新版的已经已经迁移

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

sudo apt-get install libgtest-dev

     

闲来无事,想尝试一下gtest/gmock,根据下载的源码包里有README,并根据自己安装过程补充记录如下,以便以后查询

1.获取GTest/GMock源码

从Google网站上http://code.google.com/p/googlemock/downloads/list下载GMock源码(GMock源码中包含GTest源码,无需另外下载GTest源码)

放到本地目录,我下载的GMock源码版本是gmock-1.7.0,选择放在/home/USERNAME/Download下,解压,生成gmock-1.7.0

cd gmock-1.7.0

2.创建连接库

生成gtest-all.o :         g++ -isystem gtest/include -I./gtest -isystem ./include -I. -pthread -c ./gtest/src/gtest-all.cc

生成gmock-all.o :      g++ -isystem gtest/include -I./gtest -isystem ./include -I. -pthread -c ./src/gmock-all.cc 

生成libgtest.a和libgmock.a :    ar -rv libgmock.a gtest-all.o gmock-all.o

3.拷贝文件到/use/local目录

将gmock-1.7.0/gtest/include下面的gtest目录拷贝到/usr/local/include下

cp gmock-1.7.0/gtest/include/gtest/ /usr/local/include -r

将gmock-1.7.0/include下面的gmock目录拷贝到/usr/local/include下

cp gmock-1.7.0/include/gmock/ /usr/local/include -r

cp gmock-1.7.0/libgtest.a /usr/local/lib

cp gmock-1.7.0/libgmock.a /usr/local/lib

4.编译连接,测试

g++ -o executefile  yourcode.cpp -lpthread -lgtest -lgmock

 

you need modify the Makefile using '-pthread' instead of '-lpthread'.
Or just run command like:

sudo g++ ../samples/sample1.cc ../samples/sample1_unittest.cc /usr/src/gtest/src/gtest_main.cc /usr/src/gtest/src/gtest-all.cc  -I/usr/src/gtest/include -I/usr/src/gtest -g -Wall -Wextra -pthread -o sample1_unitte

sudo ./sample1_unittest --gtest_output=xml

  --gtest_output=xml[:DIRECTORY_PATH/|:FILE_PATH]
      Generate an XML report in the given directory or with the given file
      name. FILE_PATH defaults to test_details.xml.

最后附上GTest/GMock学习文档:

GTest学习文章:

http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html

GMock三篇学习文章:

1,http://code.google.com/p/googlemock/wiki/ForDummies

2,http://code.google.com/p/googlemock/wiki/CheatSheet

3,http://code.google.com/p/googlemock/wiki/CookBook

按上述顺序阅读,最后一篇文章比较长。

 

注:如果不用gmock,仅仅用到gtest,可以将上述gmock部分内容去掉。

对于 c++ 来说写单元测试和 mock 框架不是一件容易的事情。还好, Google 为我们搭建了一个出色的单元测试和 mock 框架。网上的例子很多都过多强调概念,本文用一个简单的例子让大家对于什么是 gtest 和 gmock 让大家有一个直观的了解,让大家很快上手,就像写 hello word 一样容易。

gtest&gmock 的 1.6 版本的使用 make 编译,新版的已经已经迁移到 github 上使用 cmake 编译,安装过程很多,这里不在重复,如果大家有需要再单独写。

1.下载安装 Google Test and  Google Mock

2. 编译生成静态库gtest_main.a gmock_main.a (包含main库后不需要自己写main函数)

gmock用来对与为实现对象的接口模拟。

我们有一个Messgener.h接口,它的getMessage目前还没有实现,可以使用mock类提供的宏来模拟,这样就可以调试客户端程序,屏蔽Messgener.h的具体实现


#ifndef SRC_MESSENGER_H_
#define SRC_MESSENGER_H_

#include <string>
using namespace std;

class Messenger
{
public:
    virtual ~Messenger() {}
    virtual string getMessage() = 0;
};

#endif /* SRC_MESSENGER_H_ */

Messenger.h 的 mock 类

 

#ifndef SRC_MOCKMESSENGER_H_
#define SRC_MOCKMESSENGER_H_

#include "Messenger.h"
#include <string>
#include <gmock/gmock.h>
using namespace std;

class MockMessenger : public Messenger
{
public:
    MOCK_METHOD0(getMessage, string());
};

#endif /* SRC_MOCKMESSENGER_H_ */

调用Messenger.h的客户端程序

HelloWorld.h


#ifndef SRC_HELLOWORLD_H_
#define SRC_HELLOWORLD_H_

#include <string>
#include "Messenger.h"
using namespace std;

class HelloWorld
{
public:
    HelloWorld();
    virtual ~HelloWorld();
    string getMessage(Messenger* messenger) const;
};

#endif /* SRC_HELLOWORLD_H_ */

HelloWorld.cpp


#include "HelloWorld.h"
#include "Messenger.h"

HelloWorld::HelloWorld()
{
}

HelloWorld::~HelloWorld()
{
}

string HelloWorld::getMessage(Messenger* messenger) const
{
    return messenger->getMessage();
}

有了要测试的代码和依赖的接口的mock模拟类,下面是gtest的单元测试写法:


#include "HelloWorld.h"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "MockMessenger.h"
#include <string>
#include <memory>
using namespace testing;

TEST(HelloWorldTest, getMessage)
{
    MockMessenger messenger;
    std::string msg = "Hello World";
    EXPECT_CALL(messenger, getMessage()).WillRepeatedly(Return(ByRef(msg)));

    HelloWorld helloWorld;
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
    EXPECT_EQ("Hello World", helloWorld.getMessage(&messenger));
}

本文基于笔者的实际开发经验,言简意赅地讲解了C/C++单元测试框架gtest的主要使用方法和注意事项,并设计了若干可编译的精简示例,给出了运行效果图。既可以用作gtest的入门教程,也适合作为工作中的快速参考。

AD:


 

Google C++ Testing Framework(简称gtest,http://code.google.com/p/googletest/)是Google公司发布的一个开源C/C++单元测试框架,已被应用于多个开源项目及Google内部项目中,知名的例子包括Chrome Web浏览器、LLVM编译器架构、Protocol Buffers数据交换格式及工具等。

优秀的C/C++单元测试框架并不算少,相比之下gtest仍具有明显优势。与CppUnit比,gtest需要使用的头文件和函数宏更集中,并支持测试用例的自动注册。与CxxUnit比,gtest不要求Python等外部工具的存在。与Boost.Test比,gtest更简洁容易上手,实用性也并不逊色。Wikipedia给出了各种编程语言的单元测试框架列表(http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks)。

一、基本用法

gtest当前的版本是1.5.0,如果使用Visual C++编译,要求编译器版本不低于7.1(Visual C++ 2003)。如下图所示,它的msvc文件夹包含Visual C++工程和项目文件,samples文件夹包含10个使用范例。

gtest和gmock的关系_gtest教程

一般情况下,我们的单元测试代码只需要包含头文件gtest.h。gtest中常用的所有结构体、类、函数、常量等,都通过命名空间testing访问,不过gtest已经把最简单常用的单元测试功能包装成了一些带参数宏,因此在简单的测试中常常可以忽略命名空间的存在。

按照gtest的叫法,宏 TEST为特定的测试用例(Test Case)定义了一个可执行的测试(Test)。它接受用户指定的测试用例名(一般取被测对象名)和测试名作为参数,并划出了一个作用域供填充测试宏语句和普通的C++代码。一系列TEST的集合就构成一个简单的测试程序。
常用的测试宏如下表所示。以 ASSERT_开头和以 EXPECT_开头的宏的区别是,前者在测试失败时会给出报告并立即终止测试程序,后者在报告后继续执行测试程序。
ASSERT宏
EXPECT宏
功能
ASSERT_TRUE
EXPECT_TRUE
判真
ASSERT_FALSE
EXPECT_FALSE
判假
ASSERT_EQ
EXPECT_EQ
相等
ASSERT_NE
EXPECT_NE
不等
ASSERT_GT
EXPECT_GT
大于
ASSERT_LT
EXPECT_LT
小于
ASSERT_GE
EXPECT_GE
大于或等于
ASSERT_LE
EXPECT_LE
小于或等于
ASSERT_FLOAT_EQ
EXPECT_FLOAT_EQ
单精度浮点值相等
ASSERT_DOUBLE_EQ
EXPECT_DOUBLE_EQ
双精度浮点值相等
ASSERT_NEAR
EXPECT_NEAR
浮点值接近(第3个参数为误差阈值)
ASSERT_STREQ
EXPECT_STREQ
C字符串相等
ASSERT_STRNE
EXPECT_STRNE
C字符串不等
ASSERT_STRCASEEQ
EXPECT_STRCASEEQ
C字符串相等(忽略大小写)
ASSERT_STRCASENE
EXPECT_STRCASENE
C字符串不等(忽略大小写)
ASSERT_PRED1
EXPECT_PRED1
自定义谓词函数,
(pred, arg1)(还有_PRED2, …, 
_PRED5
 
写个简单的测试试一下。假设我们实现了一个加法函数:
      
      
      
  1. // add.h  
  2. #pragma once  
  3. inline int Add(int i, int j) { return i+j; } 
对应的单元测试程序可以这样写:
      
      
      
  1. // add_unittest.cpp  
  2. #include "add.h"  
  3. #include <gtest/gtest.h>  
  4.    
  5. TEST(Add, 负数) {  
  6.  EXPECT_EQ(Add(-1,-2), -3);  
  7.  EXPECT_GT(Add(-4,-5), -6); // 故意的  
  8. }  
  9.    
  10. TEST(Add, 正数) {  
  11.  EXPECT_EQ(Add(1,2), 3);  
  12.  EXPECT_GT(Add(4,5), 6);  
代码中,测试用例 Add包含两个测试,正数和负数(这里利用了Visual C++ 2005以上允许标识符包含Unicode字符的特性)。编译运行效果如下:
在控制台界面中,通过的测试用绿色表示,失败的测试用红色表示。双横线分隔了不同的测试用例,其中包含的每个测试的启动与结果用单横线和RUN … OK或RUN … FAILED标出。失败的测试会打印出代码行和原因,测试程序最后为所有用例和测试显示统计结果。建议读者试一下换成 ASSERT_宏的不同之处。
每个测试宏还可以使用 <<运算符在测试失败时输出自定义信息,如:
      
      
      
  1. ASSERT_EQ(M[i], N[j]) << "i = " << i << ", j = " << j; 
编译命令行中,gtest_mt.lib和gtest_main_mt.lib就是前面使用VC项目文件生成的静态库。有意思的是,测试代码不需要注册测试用例,也不需要定义 main函数,这是gtest通过后一个静态库自动完成的,它的实现代码如下:
      
      
      
  1. // gtest-main.cc  
  2. int main(int argc, char **argv) {  
  3.  std::cout << "Running main() from gtest_main.cc\n";  
  4.  testing::InitGoogleTest(&argc, argv);  
  5.  return RUN_ALL_TESTS();  
其中,函数 InitGoogleTest负责注册需要运行的所有测试用例,宏 RUN_ALL_TEST负责执行所有测试,如果全部成功则返回0,否则返回1。当然,我们也可以仅链接gtest_mt.lib,自己提供 main函数。
二、测试固件
很多时候,我们想在不同的测试执行前创建相同的配置环境,在测试执行结束后执行相应的清理工作,测试固件(Test Fixture)为这种需求提供了方便。“Fixture”是一个汉语中不易直接对应的词,《美国传统词典》对它的解释是“(作为附属物的)固定装置;被固定的状态”。在单元测试中,Fixture的作用是为测试创建辅助性的上下文环境,实现测试的初始化和终结与测试过程本身的分离,便于不同测试使用相同代码来搭建固定的配置环境。用体操比赛的说法,测试过程体现了特定测试的自选动作,测试固件则体现了对一系列测试(在开始和结束时)的规定动作。有些讲单元测试的书籍直接把测试固件称为Scaffolding(脚手架)。
使用测试固件比单纯调用 TEST宏稍微麻烦一些:
1.
        从gtest的 testing::Test类派生一个类,用 public或 protected定义以下所有成员。
2.
        (可选)建立环境:使用默认构造函数,或定义一个虚成员函数 virtual void SetUp()。
3.
        (可选)销毁环境:使用析构函数,或定义一个虚成员函数 virtual void TearDown()。
4.
        用 TEST_F定义测试,写法与 TEST相同,但测试用例名必须为上面定义的类名。
每个带固件的测试的执行顺序是:
1.
        调用默认构造函数创建一个新的带固件对象。
2.
        立即调用 SetUp函数。
3.
        运行 TEST_F体。
4.
        立即调用 TearDown函数。
5.
        调用析构函数销毁类对象。

gtest和gmock的关系_gtest教程

从gtest的实现代码可以看到, TEST_F又从用户定义的类自动派生了一个类,因此要求 public或 protected的访问权限;大括号里的内容被扩展成一个名为 TestBody的虚成员函数的函数体,因此可以在其中直接访问成员变量和成员函数。其实 TEST也采用了相同的实现机制,只是它直接从gtest的 testing::Test自动派生类,所以可以指定任意用例名。 testing::Test类的 SetUp和 TearDown都是空函数,所以它只执行测试步骤,没有环境的创建和销毁。
借用上面Add函数写个固件测试的例子:
      
      
      
  1. // add_unittest2.cpp  
  2. #include "add.h"  
  3. #include <stdio.h>  
  4. #include <gtest/gtest.h>  
  5.    
  6. class AddTest: public testing::Test  
  7. {  
  8. public:  
  9.  virtual void SetUp()    { puts("SetUp()"); }  
  10.  virtual void TearDown() { puts("TearDown()"); }  
  11. };  
  12.    
  13. TEST_F(AddTest, 正数) {  
  14.  ASSERT_GT(Add(1,2), 3); // 故意的  
  15.  ASSERT_EQ(Add(4,5), 6); // 也是故意的  
编译运行效果如下:
必须强调,每个 TEST_F开始都创建了一个新的带固件对象,因此每个测试都使用独立的完全相同的初始环境,各测试可以按任意顺序执行(参见–gtest_shuffle命令行选项)。但在某些情况下,我们可能需要在各个测试间共享一个相同的环境来保存和传递状态,或者环境的状态是只读的,可以只初始化一次,再或者创建环境的过程开销很高,要求只初始化一次。共享某个固件环境的所有测试合称为一个“测试套件”(Test Suite),gtest中利用静态成员变量和静态成员函数实现这个概念:
1.
        (可选)在 testing::Test的派生类中,定义若干静态成员变量来维护套件的状态。
2.
        (可选)建立共享环境:定义一个静态成员函数 static void SetUpTestCase()。
3.
        (可选)销毁共享环境:定义一个静态成员函数 static void TearDownCase()。
另外,还可以使用gtest的 Environment类来建立和销毁所有测试共用的全局环境(对应于上图显示的“Global test environment set-up”和“Global test environment tear-down”):
      
      
      
  1. class Environment {  
  2.  public:  
  3.  virtual ~Environment() {}  
  4.  virtual void SetUp() {}  
  5.  virtual void TearDown() {}  
  6. }; 
gtest文档建议测试程序自己定义 main函数并在其中创建和注册全局环境对象:
      
      
      
  1. Environment* AddGlobalTestEnvironment(Environment* env); 
三、异常测试
C程序中要返回出错信息,可以利用特定的函数返回值、函数的输出(outbound)参数、或者设置全局变量(如C标准库定义的 errno,Windows API中的“上次错误”(last error)代码,Winsock中与每个socket相关联的错误代码)。C++程序常用异常(exception)来返回出错信息,gtest为异常测试提供了专用的测试宏:
ASSERT宏
EXPECT宏
功能
ASSERT_NO_THROW
EXPECT_NO_THROW
不抛出异常,参数为
(statement)
ASSERT_ANY_THROW
EXPECT_ANY_THROW
抛出异常,参数为
(statement)
ASSERT_THROW
EXPECT_THROW
抛出特定类型的异常,参数为
(statement, type)
 
需要注意,这些测试宏都接受C/C++语句作为参数,所以既可以像前面那样传递表达式,也可以传递用大括号包起来的代码块。
借助下面的被测函数:
      
      
      
  1. // divide.h  
  2. #pragma once  
  3. #include <stdexcept>  
  4.    
  5. int divide(int dividend, int divisor) {  
  6.  if(!divisor) {  
  7.     throw std::length_error("can't be divided by 0"); // 故意的  
  8.  }  
  9.  return dividend / divisor;  
测试程序如下:
      
      
      
  1. // divide-unittest.cpp  
  2. #include <gtest/gtest.h>  
  3. #include "./divide.h"  
  4.    
  5. TEST(Divide, ByZero) {  
  6.  EXPECT_NO_THROW(divide(-1, 2));  
  7.    
  8.  EXPECT_ANY_THROW({  
  9.     int k = 0;  
  10.     divide(k, k);  
  11.  });  
  12.    
  13.  EXPECT_THROW(divide(100000, 0), std::invalid_argument);  
编译运行效果如下

gtest和gmock的关系_gtest教程

容易想到,gtest的这些异常测试宏是用C++的 try … catch语句来实现的:
      
      
      
  1. try {  
  2.  statement;  
  3. }  
  4. catch(type const&) {  
  5.  // throw  
  6. }  
  7. catch(...) {  
  8.  // any throw  
  9. }  
  10. // no throw 
如果把上图中Visual C++的编译选项/EHsc换成/EHa, try … catch就可以同时支持C++风格的异常和Windows系统的结构化异常(SEH)。这样,即使删掉 divide函数里的 if判断,测试代码的 EXPECT_ANY_THROW宏也会成功捕获异常。
遗憾的是,目前仅使用这些测试宏无法得到获得被抛出异常的详细信息(如 divide函数中的报错文本),这和gtest自身不愿意使用C++异常有关。
四、值参数化测试
有些时候,我们需要对代码实现的功能使用不同的参数进行测试,比如使用大量随机值来检验算法实现的正确性,或者比较同一个接口的不同实现之间的差别。gtest把“集中输入测试参数”的需求抽象出来提供支持,称为值参数化测试(Value Parameterized Test)。
值参数化测试包括4个步骤:
1.
        从gtest的 TestWithParam模板类派生一个类(记为 C),模板参数为需要输入的测试参数的类型。由于 TestWithParam本身是从 Test派生的,所以 C就成了一个测试固件类。
2.
        在 C中,可以实现诸如 SetUp、 TearDown等方法。特别地,测试参数由 TestWithParam实现的 GetParam()方法依次返回。
3.
        使用 TEST_P(而不是 TEST_F)定义测试。
4.
        使用 INSTANTIATE_TEST_CASE_P宏集中输入测试参数,它接受3个参数:任意的文本前缀,测试类名(这里即为 C),以及测试参数值序列。gtest框架依次使用这些参数值生成测试固件类实例,并执行用户定义的测试。
gtest提供了专门的模板函数来生成参数值序列,如下表所示:
参数值序列生成函数
含义
Bool()
生成序列
{false, true}
Range(begin, end[, step])
生成序列
{begin, begin+step, begin+2*step, 
…} (不含
end),
step默认为1
Values(v1, v2, 
…, 
vN)
生成序列
{v1, v2, 
…, 
vN}
ValuesIn(container)
ValuesIn(iter1, iter2)
枚举STL 
container,或枚举迭代器范围
[iter1, iter2)
Combine(g1, g2, 
…, 
gN)
生成
g1
g2, …, 
gN的笛卡尔积,其中g1
g2, …, 
gN均为参数值序列生成函数(要求C++0x的<tr1/tuple>
 
写个小程序试一下。假设我们实现了一种快速累加算法,希望使用另一种直观算法进行正确性校验。算法实现和测试代码如下
      
      
      
  1. // addupto.h  
  2.    
  3. #pragma once  
  4.    
  5. inline unsigned NaiveAddUpTo(unsigned n) {  
  6.     unsigned sum = 0;  
  7.     for(unsigned i = 1; i <= n; ++i) sum += i;  
  8.     return sum;  
  9. }  
  10.    
  11. inline unsigned FastAddUpTo(unsigned n) {  
  12.     return n*(n+1)/2;  
测试程序如下:
      
      
      
  1. // addupto_test.cpp  
  2.    
  3. #include <gtest/gtest.h>  
  4. #include "addupto.h"  
  5.    
  6. class AddUpToTest : public testing::TestWithParam<unsigned>  
  7. {  
  8. public:  
  9.     AddUpToTest() { n_ = GetParam(); }  
  10. protected:  
  11.     unsigned n_;  
  12. };  
  13.    
  14. TEST_P(AddUpToTest, Calibration) {  
  15.     EXPECT_EQ(NaiveAddUpTo(n_), FastAddUpTo(n_));  
  16. }  
  17.    
  18. INSTANTIATE_TEST_CASE_P(  
  19.     NaiveAndFast, // prefix  
  20.     AddUpToTest,   // test case name  
  21.     testing::Range(1u, 1000u) // parameters  
  22. ); 
 
注意 TestWithParam的模板参数设置为 unsigned类型,而在代码倒数第2行,两个常量值都加了 u后缀来指定为 unsigned类型。熟悉C++的读者应该知道,模板函数在进行类型推断(deduction)时匹配相当严格,不像普通函数那样允许类型提升(promotion)。如果上面省略 u后缀,就会造成编译错误。当然还可以显式指定模板参数: testing::Range<unsigned>(1, 1000)。
运行效果如下,这里省略了开头的大部分输出(命令行窗口设置的缓冲区高度为3000行)。

gtest和gmock的关系_gtest教程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/188112.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 使用Boostrap V4,左侧菜单栏可缩进,并根据屏幕宽度自适应大小。[通俗易懂]

    使用Boostrap V4,左侧菜单栏可缩进,并根据屏幕宽度自适应大小。[通俗易懂]使用Boostrap V4,左侧菜单栏可缩进,并根据屏幕宽度自适应大小。

  • lombok @Accessors用法「建议收藏」

    @Accessors翻译是存取器。通过该注解可以控制getter和setter方法的形式。fluent若为true,则getter和setter方法的方法名都是属性名,且setter方法返回当前对象。@Data@Accessors(fluent=true)classUser{ privateIntegerid; privateStringname; //…

  • 机械振动论文带有simulink分析的_matlab振动仿真实例

    机械振动论文带有simulink分析的_matlab振动仿真实例1、内容简介1、汽车传动系统的力学模型的讨论2、SIMULINK介绍3、(激励源分析并建立相应的SIMULINK模块)包括发动机动力源模型,行驶工况等4、分析扭振特性5、提出改进手段并比较改进前后系统扭振响应340-可以交流、咨询、答疑2、内容说明汽车动力传动系统是一个具有多自由度的、连续的、有阻尼系统。传动系统的振动主要有横向振动、扭转振动、纵向振动。并且汽车传动系统的扭转振动是一个非常重要的振动形式。当汽车制动、起步、换档时,这些非稳定工况下汽车传动系由于受到非周期的冲击性干扰力而产生的振动。当汽车正

    2022年10月15日
  • 管理大数据存储的十大技巧「建议收藏」

    管理大数据存储的十大技巧「建议收藏」数据本地化是为了确保大数据集存储在计算节点附近便于分析。对于Hadoop,这意味着管理数据节点,向MapReduce提供存储以便充分执行分析。它实用有效但也出现了大数据存储集群的独立操作问题。以下十项是Hadoop环境中管理大数据存储技巧。在1990年,每一台应用服务器都倾向拥有直连式系统(DAS)。SAN的构建则是为了更大的规模和更高的效率提供共享的池存储。Hadoop已经逆转了这一趋势回归DA…

  • wptx64能卸载吗_Win10自带应用卸载教程(本人亲测)

    wptx64能卸载吗_Win10自带应用卸载教程(本人亲测)使用win10有一段时间了,其中也用过诸如腾讯电脑管家、软媒魔方等工具对开机启动项进行过优化,多数时候都没出现问题,但最近几次优化使系统出现了各种问题。现在来总结一下,win10的那些服务项目不能动,不能禁止开机启动,不能关闭后台驻留。CoreMessaging:重要进程,关键系统进程,禁用后无法进入系统,ctrl+alt+del键都无效;TaskScheduler:windows系统任务调度程序…

  • vue入门教程(一)「建议收藏」

    vue入门教程(一)「建议收藏」1.vue简介1.1vue是什么官网:https://cn.vuejs.org/Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue也完全能够为复杂的单页应用提供驱动。1.2vue的特点1)遵循MVVM模式2)编码简洁,体积小,运行效率高,适合移动/PC端开发.

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号