feat: OpenWeatherMap tests

This commit is contained in:
Martin Eyben 2024-11-24 00:18:19 +01:00
parent 423e1a44f3
commit 68abfe66fa
6 changed files with 1579 additions and 31 deletions

View File

@ -9,6 +9,7 @@ import eirb.pg203.utils.JSONFetcher;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
@ -23,29 +24,29 @@ import eirb.pg203.WeatherData.Condition;
public class OpenWeatherMap implements WeatherDataAPI {
private static final String forecastBaseURL = "https://api.openweathermap.org/data/2.5/forecast";
private String APIKey;
private static final JSONFetcherInterface JSONFetcher = new JSONFetcher();
Clock clock = Clock.systemUTC();
JSONFetcherInterface JSONFetcher = new JSONFetcher();
OpenWeatherMap(String APIKey) {
this.APIKey = APIKey;
}
private JSONObject fetchWeather(int days, City city) throws IOException {
private JSONObject fetchWeather(City city) throws IOException {
URL url = URI.create(
String.format(Locale.ENGLISH, forecastBaseURL + "?appid=%s&lat=%.2f&lon=%.2f&units=metric",
APIKey,
city.getCityCoords().getLat(),
city.getCityCoords().getLon(),
days
city.getCityCoords().getLon()
)
).toURL();
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");
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;
int dataCount = 0;
float temp_c = 0;
@ -91,7 +92,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
return new WeatherData(
new City(city),
Instant.now().plusSeconds(day * 24 * 3600),
Instant.now(clock).plusSeconds(day * 24 * 3600),
temp_c,
windSpeed,
windDirection,
@ -104,7 +105,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
*/
@Override
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);
}
@ -116,7 +117,7 @@ public class OpenWeatherMap implements WeatherDataAPI {
@Override
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<>();
@ -133,4 +134,9 @@ public class OpenWeatherMap implements WeatherDataAPI {
public String getAPIName() {
return "OpenWeatherMap";
}
@Override
public String toString() {
return this.getAPIName();
}
}

View File

@ -14,7 +14,6 @@ import java.util.stream.Stream;
public class WeatherAPITest {
private static final String APIKey = "realKey";
private static final float epsilon = 0.01F;
private WeatherAPI weatherAPI;
@BeforeEach
@ -23,19 +22,6 @@ public class WeatherAPITest {
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
public void testGetAPIName() {
Assertions.assertEquals("WeatherAPI", weatherAPI.getAPIName());

View File

@ -1,5 +1,6 @@
package eirb.pg203;
import eirb.pg203.fakeJSONFetcher.FakeJSONFetcherOpenWeatherMap;
import eirb.pg203.fakeJSONFetcher.FakeJSONFetcherWeatherAPI;
import org.junit.jupiter.api.Assertions;
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 java.io.IOException;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.stream.Stream;
@ -22,6 +26,18 @@ public class WeatherDataAPITest {
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
* @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(), 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(), 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);
/* Temperatures */
Assertions.assertEquals(expectedTemp, weatherData.getTemp());
Assertions.assertEquals(expectedTemp, weatherData.getTemp(), epsilon);
/* Condition */
Assertions.assertEquals(expectedCond, weatherData.getCondition());
/* Wind */
Assertions.assertTrue(expectedWindSpeed - weatherData.getWindSpeed() < epsilon);
Assertions.assertTrue(expectedWindAngle - weatherData.getWindDirectionAngle() < epsilon);
Assertions.assertEquals(expectedWindSpeed, weatherData.getWindSpeed(), epsilon);
Assertions.assertEquals(expectedWindAngle, weatherData.getWindDirectionAngle(),epsilon);
}
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};
float[] weatherAPIExpectedWindSpeed = {17.45F, 23.03F, 13.19F, 17.45F};
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(
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);
/* Temperatures */
Assertions.assertEquals(expectedTemperatures[index], weatherData.getTemp());
Assertions.assertEquals(expectedTemperatures[index], weatherData.getTemp(), epsilon);
/* Weather condition */
Assertions.assertEquals(expectedConditions[index], weatherData.getCondition());
/* Wind */
Assertions.assertTrue(expectedWindSpeed[index] - weatherData.getWindSpeed() < epsilon);
Assertions.assertTrue(expectedWindDirection[index] - weatherData.getWindDirectionAngle() < epsilon);
Assertions.assertEquals(expectedWindSpeed[index],weatherData.getWindSpeed(), 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)
);
}
}

View File

@ -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

View File

@ -0,0 +1,4 @@
{
"cod": 401,
"message": "Invalid API key. Please see https://openweathermap.org/faq#error401 for more info."
}