0%

Unittest_GRPC

Introduce

I tried to merge unittest into my server project which based on GRPC. I use Google Test as the unittest library. Hope this article can give you merge Google Test into your exist project.

Google Test

  1. compile Google Test samples
1
2
3
4
5
git clone https://github.com/google/googletest.git
cd googletest/googletest
cmake -Dgtest_build_samples=ON ./
make
ls samples

You can read samples in googletest/googletest/samples to be familiar with Google Test

  1. Makefile prepared by Google
1
2
3
cd googletest/googletest/make
vim Makefile
make

Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# A sample Makefile for building Google Test and using it in user
# tests. Please tweak it to suit your environment and project. You
# may want to move it to your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.

# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.

# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = ..

# Where to find user code.
USER_DIR = ../samples

# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include

# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread

# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = sample1_unittest

# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h

# House-keeping build targets.

all : $(TESTS)

clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o

# Builds gtest.a and gtest_main.a.

# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc

gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^

gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^

# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.

sample1.o : $(USER_DIR)/sample1.cc $(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1.cc

sample1_unittest.o : $(USER_DIR)/sample1_unittest.cc \
$(USER_DIR)/sample1.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/sample1_unittest.cc

sample1_unittest : sample1.o sample1_unittest.o gtest_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@

This Makefile can be used to compile sample1_unittest.cc.
Our new Makefile for unittest can be based on this prepared Makefile.

Write Test Class

To test our server, we need write a simple client to visit the server.
First of all, we can learning write a simple client from google’s document.

This is part of my test client. Generally, it define a class which can connect our server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// user.h
#include <iostream>
#include <memory>
#include <string>
#include <pthread.h>
#include <thread>
#include <unistd.h>
#include <vector>

#include <grpc++/grpc++.h>
#include <grpc/grpc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>


#include "../../iShare_source/iShare.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using grpc::ClientReader;
using helloworld::Inf;
using helloworld::Greeter;
using helloworld::User_detail;
using helloworld::Reply_inf;
using helloworld::Repeated_string;
using helloworld::Search_result;
using helloworld::Login_m;
using helloworld::Sign_m;

using namespace std;

class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}

// Assambles the client's payload, sends it and presents the response back
// from the server.
User_detail Test_User_inf(Inf request);
Reply_inf Test_Login(Login_m request);


private:
std::unique_ptr<Greeter::Stub> stub_;
};

User_detail GreeterClient::Test_User_inf(Inf request) {
ClientContext context;
User_detail reply;
Status status = stub_->User_inf(&context, request, &reply);
return reply;
}

Reply_inf GreeterClient::Test_Login(Login_m request) {
ClientContext context;
Reply_inf reply;
Status status = stub_->Login(&context, request, &reply);
return reply;
}

Write Unittest File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <limits.h>
#include "user.h"
#include "gtest/gtest.h"

TEST(iShare_user_unittest, user_inf) {
GreeterClient greeter(grpc::CreateChannel(
"localhost:50056", grpc::InsecureChannelCredentials()));
Inf request;
request.set_information("1");

User_detail reply = greeter.Test_User_inf(request);

EXPECT_EQ(5, reply.friends_id_size());
EXPECT_EQ(5, reply.friends_name_size());
}

Makefile

After we finished those files, we can start to modify the Makfile for unittest.
Compare this modified Makefile with original Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file.
GTEST_DIR = /home/ubuntu/Program/third_part_library/googletest/googletest

# Where to find user code.
USER_DIR = .

# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include

# Flags passed to the C++ compiler.
CXXFLAGS += -std=c++11 -g -Wall -Wextra -pthread

# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = user_unittest

# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h

# House-keeping build targets.

all : $(TESTS)

clean :
rm -f $(TESTS) gtest.a gtest_main.a *.o

# Builds gtest.a and gtest_main.a.

# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

# For simplicity and to avoid depending on Google Test's
# implementation details, the dependencies specified below are
# conservative and not optimized. This is fine as Google Test
# compiles fast and for ordinary users its source rarely changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest-all.cc

gtest_main.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \
$(GTEST_DIR)/src/gtest_main.cc

gtest.a : gtest-all.o
$(AR) $(ARFLAGS) $@ $^

gtest_main.a : gtest-all.o gtest_main.o
$(AR) $(ARFLAGS) $@ $^

# Builds a sample test. A test should link with either gtest.a or
# gtest_main.a, depending on whether it defines its own main()
# function.


user_unittest.o : $(USER_DIR)/user_unittest.cc \
$(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/user_unittest.cc

user_unittest : user_unittest.o gtest_main.a ../../iShare_source/iShare.pb.o ../../iShare_source/iShare.grpc.pb.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -L/usr/local/lib `pkg-config --libs grpc++ grpc` -Wl,\
--no-as-needed -lgrpc++_reflection -Wl,--as-needed -lprotobuf -lpthread -ldl $^ -o $@

Sample Project

You can find my unittest project here