feat: OpenWeatherMap tests
This commit is contained in:
parent
423e1a44f3
commit
68abfe66fa
@ -9,6 +9,7 @@ import eirb.pg203.utils.JSONFetcher;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.time.Clock;
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
@ -23,29 +24,29 @@ import eirb.pg203.WeatherData.Condition;
|
|||||||
public class OpenWeatherMap implements WeatherDataAPI {
|
public class OpenWeatherMap implements WeatherDataAPI {
|
||||||
private static final String forecastBaseURL = "https://api.openweathermap.org/data/2.5/forecast";
|
private static final String forecastBaseURL = "https://api.openweathermap.org/data/2.5/forecast";
|
||||||
private String APIKey;
|
private String APIKey;
|
||||||
private static final JSONFetcherInterface JSONFetcher = new JSONFetcher();
|
Clock clock = Clock.systemUTC();
|
||||||
|
JSONFetcherInterface JSONFetcher = new JSONFetcher();
|
||||||
|
|
||||||
OpenWeatherMap(String APIKey) {
|
OpenWeatherMap(String APIKey) {
|
||||||
this.APIKey = APIKey;
|
this.APIKey = APIKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONObject fetchWeather(int days, City city) throws IOException {
|
private JSONObject fetchWeather(City city) throws IOException {
|
||||||
URL url = URI.create(
|
URL url = URI.create(
|
||||||
String.format(Locale.ENGLISH, forecastBaseURL + "?appid=%s&lat=%.2f&lon=%.2f&units=metric",
|
String.format(Locale.ENGLISH, forecastBaseURL + "?appid=%s&lat=%.2f&lon=%.2f&units=metric",
|
||||||
APIKey,
|
APIKey,
|
||||||
city.getCityCoords().getLat(),
|
city.getCityCoords().getLat(),
|
||||||
city.getCityCoords().getLon(),
|
city.getCityCoords().getLon()
|
||||||
days
|
|
||||||
)
|
)
|
||||||
).toURL();
|
).toURL();
|
||||||
|
|
||||||
return JSONFetcher.fetch(url);
|
return JSONFetcher.fetch(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
private WeatherData getWeatherDataFromForecast(JSONObject response, int day, String city) {
|
||||||
JSONArray list = response.getJSONArray("list");
|
JSONArray list = response.getJSONArray("list");
|
||||||
|
|
||||||
DayOfWeek targetedDay = Instant.now().plusSeconds(day * 24 * 3600).atZone(ZoneId.systemDefault()).getDayOfWeek();
|
DayOfWeek targetedDay = Instant.now(clock).plusSeconds(day * 24 * 3600).atZone(ZoneId.systemDefault()).getDayOfWeek();
|
||||||
DayOfWeek dayOfWeek;
|
DayOfWeek dayOfWeek;
|
||||||
int dataCount = 0;
|
int dataCount = 0;
|
||||||
float temp_c = 0;
|
float temp_c = 0;
|
||||||
@ -91,7 +92,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
|||||||
|
|
||||||
return new WeatherData(
|
return new WeatherData(
|
||||||
new City(city),
|
new City(city),
|
||||||
Instant.now().plusSeconds(day * 24 * 3600),
|
Instant.now(clock).plusSeconds(day * 24 * 3600),
|
||||||
temp_c,
|
temp_c,
|
||||||
windSpeed,
|
windSpeed,
|
||||||
windDirection,
|
windDirection,
|
||||||
@ -104,7 +105,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public WeatherData getTemperature(int day, String city) throws IOException {
|
public WeatherData getTemperature(int day, String city) throws IOException {
|
||||||
JSONObject result = fetchWeather(day+1, new City(city));
|
JSONObject result = fetchWeather(new City(city));
|
||||||
|
|
||||||
return getWeatherDataFromForecast(result, day, city);
|
return getWeatherDataFromForecast(result, day, city);
|
||||||
}
|
}
|
||||||
@ -116,7 +117,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
public ArrayList<WeatherData> getTemperatures(int days, String city) throws IOException {
|
||||||
JSONObject result = fetchWeather(days, new City(city));
|
JSONObject result = fetchWeather(new City(city));
|
||||||
|
|
||||||
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
ArrayList<WeatherData> weatherDatas = new ArrayList<>();
|
||||||
|
|
||||||
@ -133,4 +134,9 @@ public class OpenWeatherMap implements WeatherDataAPI {
|
|||||||
public String getAPIName() {
|
public String getAPIName() {
|
||||||
return "OpenWeatherMap";
|
return "OpenWeatherMap";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getAPIName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
public class WeatherAPITest {
|
public class WeatherAPITest {
|
||||||
private static final String APIKey = "realKey";
|
private static final String APIKey = "realKey";
|
||||||
private static final float epsilon = 0.01F;
|
|
||||||
private WeatherAPI weatherAPI;
|
private WeatherAPI weatherAPI;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -23,19 +22,6 @@ public class WeatherAPITest {
|
|||||||
this.weatherAPI.JSONFetcher = new FakeJSONFetcherWeatherAPI();
|
this.weatherAPI.JSONFetcher = new FakeJSONFetcherWeatherAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* For coverage (hour not yet implemented)
|
|
||||||
* @throws IOException never
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testGetTemperatureByHour() throws IOException {
|
|
||||||
String city = "Bordeaux";
|
|
||||||
Assertions.assertAll(
|
|
||||||
() -> weatherAPI.getTemperature(0,1, city)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAPIName() {
|
public void testGetAPIName() {
|
||||||
Assertions.assertEquals("WeatherAPI", weatherAPI.getAPIName());
|
Assertions.assertEquals("WeatherAPI", weatherAPI.getAPIName());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package eirb.pg203;
|
package eirb.pg203;
|
||||||
|
|
||||||
|
import eirb.pg203.fakeJSONFetcher.FakeJSONFetcherOpenWeatherMap;
|
||||||
import eirb.pg203.fakeJSONFetcher.FakeJSONFetcherWeatherAPI;
|
import eirb.pg203.fakeJSONFetcher.FakeJSONFetcherWeatherAPI;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
@ -9,6 +10,9 @@ import org.junit.jupiter.params.provider.Arguments;
|
|||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@ -22,6 +26,18 @@ public class WeatherDataAPITest {
|
|||||||
return weatherAPI;
|
return weatherAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static OpenWeatherMap openWeatherMap(){
|
||||||
|
// Fix clock for testing
|
||||||
|
String instantExpected = "2024-11-24T00:00:00.00Z";
|
||||||
|
Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.systemDefault());
|
||||||
|
|
||||||
|
OpenWeatherMap openWeatherMap= new OpenWeatherMap(APIKey);
|
||||||
|
openWeatherMap.JSONFetcher = new FakeJSONFetcherOpenWeatherMap();
|
||||||
|
openWeatherMap.clock = clock;
|
||||||
|
return openWeatherMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of args for Temperature testing
|
* List of args for Temperature testing
|
||||||
* @return Args for testing
|
* @return Args for testing
|
||||||
@ -32,7 +48,11 @@ public class WeatherDataAPITest {
|
|||||||
Arguments.arguments(weatherAPI(), 0, 8.1F,WeatherData.Condition.PARTIAL, 17.45F, 142.08F),
|
Arguments.arguments(weatherAPI(), 0, 8.1F,WeatherData.Condition.PARTIAL, 17.45F, 142.08F),
|
||||||
Arguments.arguments(weatherAPI(), 1, 13F, WeatherData.Condition.SUNNY, 23.03F, 142.58F),
|
Arguments.arguments(weatherAPI(), 1, 13F, WeatherData.Condition.SUNNY, 23.03F, 142.58F),
|
||||||
Arguments.arguments(weatherAPI(), 2, 12.7F, WeatherData.Condition.RAINY, 13.19F, 222.92F),
|
Arguments.arguments(weatherAPI(), 2, 12.7F, WeatherData.Condition.RAINY, 13.19F, 222.92F),
|
||||||
Arguments.arguments(weatherAPI(), 3, 8.1F,WeatherData.Condition.CLOUDY, 17.45F, 142.08F)
|
Arguments.arguments(weatherAPI(), 3, 8.1F,WeatherData.Condition.CLOUDY, 17.45F, 142.08F),
|
||||||
|
Arguments.arguments(openWeatherMap(), 0, 13.41F,WeatherData.Condition.PARTIAL, 5.74F, 142.13F),
|
||||||
|
Arguments.arguments(openWeatherMap(), 1, 13.29F,WeatherData.Condition.CLOUDY, 3.62F, 225.25F),
|
||||||
|
Arguments.arguments(openWeatherMap(), 2, 10.06F,WeatherData.Condition.RAINY, 2.22F, 191.75F),
|
||||||
|
Arguments.arguments(openWeatherMap(), 3, 9.88F,WeatherData.Condition.SUNNY, 2.00F, 160.00F)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,12 +64,12 @@ public class WeatherDataAPITest {
|
|||||||
weatherData = weatherDataAPI.getTemperature(day, city);
|
weatherData = weatherDataAPI.getTemperature(day, city);
|
||||||
|
|
||||||
/* Temperatures */
|
/* Temperatures */
|
||||||
Assertions.assertEquals(expectedTemp, weatherData.getTemp());
|
Assertions.assertEquals(expectedTemp, weatherData.getTemp(), epsilon);
|
||||||
/* Condition */
|
/* Condition */
|
||||||
Assertions.assertEquals(expectedCond, weatherData.getCondition());
|
Assertions.assertEquals(expectedCond, weatherData.getCondition());
|
||||||
/* Wind */
|
/* Wind */
|
||||||
Assertions.assertTrue(expectedWindSpeed - weatherData.getWindSpeed() < epsilon);
|
Assertions.assertEquals(expectedWindSpeed, weatherData.getWindSpeed(), epsilon);
|
||||||
Assertions.assertTrue(expectedWindAngle - weatherData.getWindDirectionAngle() < epsilon);
|
Assertions.assertEquals(expectedWindAngle, weatherData.getWindDirectionAngle(),epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Arguments> testGetTemperatures() {
|
private static Stream<Arguments> testGetTemperatures() {
|
||||||
@ -57,8 +77,15 @@ public class WeatherDataAPITest {
|
|||||||
WeatherData.Condition[] weatherAPIExpectedConditions = {WeatherData.Condition.PARTIAL, WeatherData.Condition.SUNNY, WeatherData.Condition.RAINY, WeatherData.Condition.CLOUDY};
|
WeatherData.Condition[] weatherAPIExpectedConditions = {WeatherData.Condition.PARTIAL, WeatherData.Condition.SUNNY, WeatherData.Condition.RAINY, WeatherData.Condition.CLOUDY};
|
||||||
float[] weatherAPIExpectedWindSpeed = {17.45F, 23.03F, 13.19F, 17.45F};
|
float[] weatherAPIExpectedWindSpeed = {17.45F, 23.03F, 13.19F, 17.45F};
|
||||||
float[] weatherAPIExpectedWindDirection = {142.08F, 142.58F, 222.92F, 142.08F};
|
float[] weatherAPIExpectedWindDirection = {142.08F, 142.58F, 222.92F, 142.08F};
|
||||||
|
|
||||||
|
float[] openWeatherMapExpectedTemperatures = {13.41F, 13.29F, 10.06F, 9.88F};
|
||||||
|
WeatherData.Condition[] openWeatherMapExpectedConditions = {WeatherData.Condition.PARTIAL, WeatherData.Condition.CLOUDY, WeatherData.Condition.RAINY, WeatherData.Condition.SUNNY};
|
||||||
|
float[] openWeatherMapExpectedWindSpeed = {5.74F, 3.62F, 2.22F, 2.00F};
|
||||||
|
float[] openWeatherMapExpectedWindDirection = {142.13F, 225.25F, 191.75F, 160F};
|
||||||
|
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.arguments(weatherAPI(), 4, weatherAPIExpectedTemperatures, weatherAPIExpectedConditions, weatherAPIExpectedWindSpeed, weatherAPIExpectedWindDirection)
|
Arguments.arguments(weatherAPI(), 4, weatherAPIExpectedTemperatures, weatherAPIExpectedConditions, weatherAPIExpectedWindSpeed, weatherAPIExpectedWindDirection),
|
||||||
|
Arguments.arguments(openWeatherMap(), 4, openWeatherMapExpectedTemperatures, openWeatherMapExpectedConditions, openWeatherMapExpectedWindSpeed, openWeatherMapExpectedWindDirection)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -75,12 +102,29 @@ public class WeatherDataAPITest {
|
|||||||
weatherData = weatherDatas.get(index);
|
weatherData = weatherDatas.get(index);
|
||||||
|
|
||||||
/* Temperatures */
|
/* Temperatures */
|
||||||
Assertions.assertEquals(expectedTemperatures[index], weatherData.getTemp());
|
Assertions.assertEquals(expectedTemperatures[index], weatherData.getTemp(), epsilon);
|
||||||
/* Weather condition */
|
/* Weather condition */
|
||||||
Assertions.assertEquals(expectedConditions[index], weatherData.getCondition());
|
Assertions.assertEquals(expectedConditions[index], weatherData.getCondition());
|
||||||
/* Wind */
|
/* Wind */
|
||||||
Assertions.assertTrue(expectedWindSpeed[index] - weatherData.getWindSpeed() < epsilon);
|
Assertions.assertEquals(expectedWindSpeed[index],weatherData.getWindSpeed(), epsilon);
|
||||||
Assertions.assertTrue(expectedWindDirection[index] - weatherData.getWindDirectionAngle() < epsilon);
|
Assertions.assertEquals(expectedWindDirection[index], weatherData.getWindDirectionAngle(), epsilon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> testGetTemperatureByHours() {
|
||||||
|
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.arguments(weatherAPI()),
|
||||||
|
Arguments.arguments(openWeatherMap())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ParameterizedTest(name = "[{0}] Get temperature for a specific hour")
|
||||||
|
@MethodSource
|
||||||
|
public void testGetTemperatureByHours(WeatherDataAPI weatherDataAPI) {
|
||||||
|
String city = "Bordeaux";
|
||||||
|
Assertions.assertAll(
|
||||||
|
() -> weatherDataAPI.getTemperature(0,1, city)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package eirb.pg203.fakeJSONFetcher;
|
||||||
|
|
||||||
|
import eirb.pg203.utils.FileResourcesUtils;
|
||||||
|
import eirb.pg203.utils.JSONFetcherInterface;
|
||||||
|
import eirb.pg203.utils.SplitQueryUrl;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FakeJSONFetcherOpenWeatherMap implements JSONFetcherInterface {
|
||||||
|
private final String apiKey = "realKey";
|
||||||
|
private final JSONObject wrongKeyResponse = FileResourcesUtils.getFileFromResourceAsJson("OpenWeatherMap/wrong-apikey.json");
|
||||||
|
|
||||||
|
private JSONObject responseExample() {
|
||||||
|
return FileResourcesUtils.getFileFromResourceAsJson("OpenWeatherMap/Bordeaux-partial-cloudy-rain-sunny.json");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public JSONObject fetch(URL url) throws IOException {
|
||||||
|
Map<String, String> params = SplitQueryUrl.splitQuery(url);
|
||||||
|
if (!params.getOrDefault("appid", "").contentEquals(apiKey))
|
||||||
|
return wrongKeyResponse;
|
||||||
|
return responseExample();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONArray fetchArray(URL url) throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
4
src/test/resources/OpenWeatherMap/wrong-apikey.json
Normal file
4
src/test/resources/OpenWeatherMap/wrong-apikey.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"cod": 401,
|
||||||
|
"message": "Invalid API key. Please see https://openweathermap.org/faq#error401 for more info."
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user