这篇文章将接着上一篇文章,将测试用例和代码补充完整,同时讨论更多关于TDD的内容。
如果你没有看过上一篇文章,这里是地址:传送门
最近忙于折腾网站挂https,以及给我的小米8刷机,博客更新进度比较慢,见谅。
测试6
TDD Step1 :编写测试用例
加入六月
TEST(monthFiveTest,day_11){
EXPECT_EQ(calculateDate(2022,6,11),162);
}
TDD Step2:编写刚好让测试用例通过的代码
把六月的情况加入代码之中
int calculateDate(int year,int month,int day){
int days = day;
for (int i = 1; i < month; i++)
{
if(i == jan || i == mar || i == may)
{
days += day_month_solar;
}else if (i == apr)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
}
return days;
}
TDD Step3:重构
代码很整洁,无需重构
测试7
TDD Step1 :编写测试用例
加入七月
TEST(monthSixTest,day_11){
EXPECT_EQ(calculateDate(2022,7,2),183);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改如下
if(i == jan || i == mar || i == may)
{
days += day_month_solar;
}else if (i == apr || i == jun)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试8
TDD Step1 :编写测试用例
加入八月
TEST(monthSevenTest,day_11){
EXPECT_EQ(calculateDate(2022,8,5),217);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改为
if(i == jan || i == mar || i == may || i == jul)
{
days += day_month_solar;
}else if (i == apr || i == jun)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试9
TDD Step1 :编写测试用例
加入九月
TEST(monthEightTest,day_11){
EXPECT_EQ(calculateDate(2022,9,11),254);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改为
if(i == jan || i == mar || i == may || i == jul || i == aug)
{
days += day_month_solar;
}else if (i == apr || i == jun)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试10
TDD Step1 :编写测试用例
加入十月
TEST(monthNineTest,day_6){
EXPECT_EQ(calculateDate(2022,10,6),279);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改为
if(i == jan || i == mar || i == may || i == jul || i == aug)
{
days += day_month_solar;
}else if (i == apr || i == jun || i == sep)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试11
TDD Step1 :编写测试用例
加入十一月
TEST(monthTenTest,day_11){
EXPECT_EQ(calculateDate(2022,11,11),315);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改为
if(i == jan || i == mar || i == may || i == jul || i == aug || i == oct)
{
days += day_month_solar;
}else if (i == apr || i == jun || i == sep)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试12
TDD Step1 :编写测试用例
加入十二月
TEST(monthElevenTest,day_31){
EXPECT_EQ(calculateDate(2022,12,31),365);
}
TDD Step2:编写刚好让测试用例通过的代码
代码主体部分修改为
if(i == jan || i == mar || i == may || i == jul || i == aug || i == oct)
{
days += day_month_solar;
}else if (i == apr || i == jun || i == sep || i == nov)
{
days += day_month_lunar;
}else if (i == feb)
{
days += day_month_feb_lunar;
}
TDD Step3:重构
代码很整洁,无需重构
测试13
TDD Step1 :编写测试用例
我们尝试改变年份
TEST(year2Test,day_31){
EXPECT_EQ(calculateDate(2000,5,11),132);
}
显然没有通过
[----------] 1 test from year2Test
[ RUN ] year2Test.day_31
D:\Projects\vscodeProjectSpace\DateTestMy\test\datet_unittest.cpp:57: Failure
Expected equality of these values:
calculateDate(2000,5,11)
Which is: 131
132
[ FAILED ] year2Test.day_31 (13 ms)
[----------] 1 test from year2Test (19 ms total)
[----------] Global test environment tear-down
[==========] 14 tests from 13 test suites ran. (210 ms total)
[ PASSED ] 13 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] year2Test.day_31
TDD Step2:编写刚好让测试用例通过的代码
造成没有通过的原因是,没有判断2月的天数变化,加上判断即可
if(i == jan || i == mar || i == may || i == jul || i == aug || i == oct)
{
days += day_month_solar;
}else if (i == apr || i == jun || i == sep || i == nov)
{
days += day_month_lunar;
}else if (i == feb)
{
if ((year % 4 == 0 && year % 100 != 0 )|| year % 400 == 0)
{
days += day_month_feb_solar;
}else{
days += day_month_feb_lunar;
}
}
TDD Step3:重构
代码开发已接近尾声,检查了不合理的命名并改正了
最后的datet.cpp
如下
#include "datet.h"
const int jan = 1;
const int feb = 2;
const int mar = 3;
const int apr = 4;
const int may = 5;
const int jun = 6;
const int jul = 7;
const int aug = 8;
const int sep = 9;
const int oct = 10;
const int nov = 11;
const int day_month_solar = 31;
const int day_month_lunar = 30;
const int day_month_feb_lunar = 28;
const int day_month_feb_solar = 29;
int calculateDate(int year,int month,int day){
int days = day;
for (int i = 1; i < month; i++)
{
if(i == jan || i == mar || i == may || i == jul || i == aug || i == oct)
{
days += day_month_solar;
}else if (i == apr || i == jun || i == sep || i == nov)
{
days += day_month_lunar;
}else if (i == feb)
{
if ((year % 4 == 0 && year % 100 != 0 )|| year % 400 == 0)
{
days += day_month_feb_solar;
}else{
days += day_month_feb_lunar;
}
}
}
return days;
}
datet_unittest.cpp
如下
#include "gtest/gtest.h"
#include "datet.h"
TEST(monthZeroTest,day_1){
EXPECT_EQ(calculateDate(2022,1,1),1);
}
TEST(monthZeroTest,day_2){
EXPECT_EQ(calculateDate(2022,1,2),2);
}
TEST(monthOneTest,day_1){
EXPECT_EQ(calculateDate(2022,2,1),32);
}
TEST(monthTwoTest,day_2){
EXPECT_EQ(calculateDate(2022,3,2),61);
}
TEST(monthThreeTest,day_2){
EXPECT_EQ(calculateDate(2022,4,2),92);
}
TEST(monthFourTest,day_11){
EXPECT_EQ(calculateDate(2022,5,11),131);
}
TEST(monthFiveTest,day_11){
EXPECT_EQ(calculateDate(2022,6,11),162);
}
TEST(monthSixTest,day_2){
EXPECT_EQ(calculateDate(2022,7,2),183);
}
TEST(monthSevenTest,day_5){
EXPECT_EQ(calculateDate(2022,8,5),217);
}
TEST(monthEightTest,day_11){
EXPECT_EQ(calculateDate(2022,9,11),254);
}
TEST(monthNineTest,day_6){
EXPECT_EQ(calculateDate(2022,10,6),279);
}
TEST(monthTenTest,day_11){
EXPECT_EQ(calculateDate(2022,11,11),315);
}
TEST(monthElevenTest,day_31){
EXPECT_EQ(calculateDate(2022,12,31),365);
}
TEST(year2Test,day_11){
EXPECT_EQ(calculateDate(2000,5,11),132);
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
结尾
通过TDD,我们似乎将一个简单的问题复杂化了。
事实上许多软件开发工作,虽然最初计划完全遵守TDD,但是最后也屈服于工期的要求,要么只编写主要的测试代码,要么完全不编写测试代码,都留待有要求再补充测试用例。然而这些测试用例在排查bug的时候也许能用得上也说不定,专注于测试用例的开发也比泛而杂的开发更专注。时间上,还真不能说谁更具有优势。
也许我从事软件开发行业几年后,对这个问题会有不同的看法。