Skip to content
Open
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c752903
Merge pull request #1 from driverdevteam/master
dariatdd Oct 17, 2018
8284ce3
4: added assumptions and architecture
dariatdd Oct 24, 2018
5ec5154
4: added steps (list of tests)
dariatdd Oct 24, 2018
0ac23db
4: red
dariatdd Oct 24, 2018
47df687
4: green
dariatdd Oct 24, 2018
a7a0048
4: refactored
dariatdd Oct 24, 2018
99276b4
4: red
dariatdd Oct 25, 2018
1ecb982
4: green
dariatdd Oct 25, 2018
31c2d01
4: refactored
dariatdd Oct 25, 2018
b3ad82c
4: red
dariatdd Oct 25, 2018
bef1275
3: green
dariatdd Oct 25, 2018
41f7d97
4: red
dariatdd Oct 25, 2018
6898ed8
4: green
dariatdd Oct 25, 2018
db7562a
4: refactored
dariatdd Oct 25, 2018
7970879
4: implemented architecture requirements
dariatdd Oct 25, 2018
eccbb66
4: red
dariatdd Oct 25, 2018
acfc3c4
4: green
dariatdd Oct 25, 2018
6e2c224
4: refactored
dariatdd Oct 25, 2018
212aa8a
4: red
dariatdd Oct 25, 2018
cf837f5
4: green
dariatdd Oct 25, 2018
7041266
4: red
dariatdd Oct 25, 2018
793a6b6
4: green
dariatdd Oct 25, 2018
8608b64
4: refactored
dariatdd Oct 25, 2018
8752880
4: red
dariatdd Oct 25, 2018
42d65bd
4: fixed expected reuslt
dariatdd Oct 25, 2018
ee382d6
4: green
dariatdd Oct 25, 2018
e815cd1
4:red
dariatdd Oct 25, 2018
feddaf5
4: green
dariatdd Oct 25, 2018
a72bf67
4: red
dariatdd Oct 25, 2018
73f3063
4: green
dariatdd Oct 25, 2018
132328c
4: green
dariatdd Oct 25, 2018
991c80b
4: red
dariatdd Oct 25, 2018
7b3e6d5
4: green
dariatdd Oct 25, 2018
c6e5de0
4: green
dariatdd Oct 25, 2018
cabb730
4: red
dariatdd Oct 25, 2018
665f69b
4: green
dariatdd Oct 25, 2018
33e32a4
4: green
dariatdd Oct 25, 2018
f82bb87
4: red
dariatdd Oct 25, 2018
7c4ae59
4: green
dariatdd Oct 25, 2018
02a9ef0
4: green
dariatdd Oct 25, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
308 changes: 304 additions & 4 deletions tdd_intro/homework/04_weather_client/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,54 @@ Each line means "<request>" : "<response>":
2. Implement IWeatherClient using fake server.
*/

/*
Assumptions:
1. To get average/minimal/maximum marks WeatherClient asks server for weather for times 03:00, 09:00, 15:00 and 21:00 and then calculates necessary value based on these data.
2. The weather is always returned from server in the further format 20;181;5.1 or as empty string in case of invalid request. The server returns data in valid format.

Architecture:
1. WeatherClient is initialized with the implementation of IWeatherServer with functionality to get raw string with weather.
2. Weather client parses the obtained raw string into Weather structure and uses it then to calculate average/minimal/maximum marks.
3. There is a separate utils method ConvertStringToWeather to parse raw string to Weather object and list if strings to list of Weather objects.
4. WeatherClient also has separate method GetWeatherMarksForDay for getting weather for all time periods during the day; returns list of strings

Steps:
1. Check ConvertStringToWeather with empty string
2. Check ConvertStringToWeather with valid weather string
3. Check ConvertStringToWeather with valid list of strings
4. Implement IWeatherServer and IWeatherClient with stubs
5. Check GetAverageTemperature for 31.08
6. Acceptance for GetAverageTemperature: check for 01.09, 02.09
7. Check GetMinimumTemperature for 31.08
8. Acceptance for GetMinimumTemperature: check for 01.09, 02.09
9. Check GetMaximumTemperature for 31.08
10. Acceptance for GetMaximumTemperature: check for 01.09, 02.09
11. Check GetAverageWindDirection for 31.08
12. Acceptance for GetAverageWindDirection: check for 01.09, 02.09
13. Check GetMaximumWindSpeed for 31.08
14. Acceptance for GetMaximumWindSpeed: check for 01.09, 02.09
*/

#include <gtest/gtest.h>
#include <gmock/gmock.h>

struct Weather
{
short temperature = 0;
unsigned short windDirection = 0;
double windSpeed = 0;
bool operator==(const Weather& right)
short temperature;
unsigned short windDirection;
double windSpeed;

bool operator==(const Weather& right) const
{
return temperature == right.temperature &&
windDirection == right.windDirection &&
std::abs(windSpeed - right.windSpeed) < 0.01;
}
};

using WeatherList = std::vector<Weather>;
using StringList = std::vector<std::string>;

class IWeatherServer
{
public:
Expand All @@ -79,3 +111,271 @@ class IWeatherClient
virtual double GetAverageWindDirection(IWeatherServer& server, const std::string& date) = 0;
virtual double GetMaximumWindSpeed(IWeatherServer& server, const std::string& date) = 0;
};

Weather ConvertStringToWeather(const std::string& rawData);
WeatherList ConvertStringToWeather(const StringList& rawDataList);

class FakeWeatherServer : public IWeatherServer
{
virtual std::string GetWeather(const std::string& request) override
{
static const std::map<std::string, std::string> weatherResults = {{"31.08.2018;03:00","20;181;5.1"},
{"31.08.2018;09:00", "23;204;4.9"},
{"31.08.2018;15:00", "33;193;4.3"},
{"31.08.2018;21:00", "26;179;4.5"},

{"01.09.2018;03:00", "19;176;4.2"},
{"01.09.2018;09:00", "22;131;4.1"},
{"01.09.2018;15:00", "31;109;4.0"},
{"01.09.2018;21:00", "24;127;4.1"},

{"02.09.2018;03:00", "21;158;3.8"},
{"02.09.2018;09:00", "25;201;3.5"},
{"02.09.2018;15:00", "34;258;3.7"},
{"02.09.2018;21:00", "27;299;4.0"},
};
auto valueIt = weatherResults.find(request);
if(valueIt != weatherResults.end())
{
return valueIt->second;
}
else
{
return "";
}
}
};

class WeatherClient : public IWeatherClient
{
public:
virtual double GetAverageTemperature(IWeatherServer& server, const std::string& date) override
{
WeatherList weatherMarks = GetWeatherMarksForDay(server, date);
double temperatureSum = 0.0;
for(const auto& mark: weatherMarks)
{
temperatureSum += mark.temperature;
}
return temperatureSum / weatherMarks.size();
}

virtual double GetMinimumTemperature(IWeatherServer& server, const std::string& date) override
{
WeatherList weatherMarks = GetWeatherMarksForDay(server, date);
auto minWeather = std::min_element(weatherMarks.begin(), weatherMarks.end(), [] (const Weather& left, const Weather& right)
{
return left.temperature < right.temperature;
});

return minWeather->temperature;
}

virtual double GetMaximumTemperature(IWeatherServer& server, const std::string& date) override
{
WeatherList weatherMarks = GetWeatherMarksForDay(server, date);
auto maxWeather = std::max_element(weatherMarks.begin(), weatherMarks.end(), [] (const Weather& left, const Weather& right)
{
return left.temperature < right.temperature;
});

return maxWeather->temperature;
}

virtual double GetAverageWindDirection(IWeatherServer& server, const std::string& date) override
{
WeatherList weatherMarks = GetWeatherMarksForDay(server, date);
double windDirectionSum = 0.0;
for(const auto& mark: weatherMarks)
{
windDirectionSum += mark.windDirection;
}
return windDirectionSum / weatherMarks.size();
}

virtual double GetMaximumWindSpeed(IWeatherServer& server, const std::string& date) override
{
WeatherList weatherMarks = GetWeatherMarksForDay(server, date);
auto maxWeather = std::max_element(weatherMarks.begin(), weatherMarks.end(), [] (const Weather& left, const Weather& right)
{
return left.windSpeed < right.windSpeed;
});

return maxWeather->windSpeed;
}

WeatherList GetWeatherMarksForDay(IWeatherServer& server, const std::string& date)
{
StringList weatherResults = {};
const StringList times = {"03:00", "09:00", "15:00", "21:00"};
for(const auto& time: times)
{
weatherResults.push_back(server.GetWeather(date + ";" + time));
}

return ConvertStringToWeather(weatherResults);
}
};

Weather ConvertStringToWeather(const std::string& rawData)
{
if(rawData.empty())
{
throw std::runtime_error("Invalid format");
}

Weather weather;

std::istringstream stream(rawData);
stream >> weather.temperature;

stream.ignore();
stream >> weather.windDirection;
stream.ignore();
stream >> weather.windSpeed;

return weather;
}

WeatherList ConvertStringToWeather(const StringList& rawDataList)
{
std::vector<Weather> result;
for(const auto& data: rawDataList)
{
result.push_back(ConvertStringToWeather(data));
}
return result;
}

TEST(ConvertStringToWeather, EmptyString)
{
EXPECT_THROW(ConvertStringToWeather(""), std::runtime_error);
}

TEST(ConvertStringToWeather, ValidString)
{
Weather etalon {20, 181, 5.1};
EXPECT_EQ(etalon, ConvertStringToWeather("20;181;5.1"));
}

TEST(ConvertStringListToWeatherList, EmptyList)
{
EXPECT_EQ(WeatherList(), ConvertStringToWeather(std::vector<std::string>()));
}

TEST(ConvertStringListToWeatherList, ValidList)
{
StringList inputData = {"20;181;5.1", "23;204;4.9"};
WeatherList etalon = {Weather {20, 181, 5.1},
Weather {23, 204, 4.9}};
EXPECT_EQ(etalon,ConvertStringToWeather(inputData));
}


TEST(GetWeatherListForDate, Date3108)
{
FakeWeatherServer server;
WeatherClient client;
WeatherList etalon = {Weather {20, 181, 5.1},
Weather {23, 204, 4.9},
Weather {33, 193, 4.3},
Weather {26, 179, 4.5}};
EXPECT_EQ(etalon, client.GetWeatherMarksForDay(server, "31.08.2018"));
}

TEST(GetWeatherListForDate, Date0109)
{
FakeWeatherServer server;
WeatherClient client;
WeatherList etalon = {Weather {19, 176, 4.2},
Weather {22, 131, 4.1},
Weather {31, 109, 4.0},
Weather {24, 127, 4.1}};
EXPECT_EQ(etalon, client.GetWeatherMarksForDay(server, "01.09.2018"));
}

TEST(GetWeatherListForDate, IncorrectServerRequest)
{
FakeWeatherServer server;
WeatherClient client;
WeatherList etalon = {Weather {19, 176, 4.2},
Weather {22, 131, 4.9},
Weather {31, 109, 4.0},
Weather {24, 127, 4.1}};
EXPECT_THROW(client.GetWeatherMarksForDay(server, "01,09.2018"), std::runtime_error);
}

TEST(GetAverageTemperature, For3108)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(25.5, client.GetAverageTemperature(server, "31.08.2018"));
}

TEST(GetAverageTemperature, Acceptance)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(24, client.GetAverageTemperature(server, "01.09.2018"));
EXPECT_EQ(26.75, client.GetAverageTemperature(server, "02.09.2018"));
}

TEST(GetMinimumTemperature, For3108)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(20, client.GetMinimumTemperature(server, "31.08.2018"));
}

TEST(GetMinimumTemperature, Acceptance)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(19, client.GetMinimumTemperature(server, "01.09.2018"));
EXPECT_EQ(21, client.GetMinimumTemperature(server, "02.09.2018"));
}

TEST(GetMiaximumTemperature, For3108)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(33, client.GetMaximumTemperature(server, "31.08.2018"));
}

TEST(GetMiaximumTemperature, Acceptance)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(31, client.GetMaximumTemperature(server, "01.09.2018"));
EXPECT_EQ(34, client.GetMaximumTemperature(server, "02.09.2018"));
}

TEST(GetMaximumWindSpeed, For3108)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(5.1, client.GetMaximumWindSpeed(server, "31.08.2018"));
}

TEST(GetMaximumWindSpeed, Acceptance)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(4.2, client.GetMaximumWindSpeed(server, "01.09.2018"));
EXPECT_EQ(4.0, client.GetMaximumWindSpeed(server, "02.09.2018"));
}

TEST(GetAverageWindDirection, For3108)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(189.25, client.GetAverageWindDirection(server, "31.08.2018"));
}

TEST(GetAverageWindDirection, Acceptance)
{
FakeWeatherServer server;
WeatherClient client;
EXPECT_EQ(135.75, client.GetAverageWindDirection(server, "01.09.2018"));
EXPECT_EQ(229, client.GetAverageWindDirection(server, "02.09.2018"));
}