Refactored code to support unit testing of coordinates as well as instrumented

pull/316/head
Loren M. Lang 2022-01-05 01:38:28 -08:00
rodzic 1df09f4bed
commit b491e99058
4 zmienionych plików z 116 dodań i 52 usunięć

Wyświetl plik

@ -1,9 +1,7 @@
package org.aprsdroid.app.testing;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.instanceOf;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
@ -12,47 +10,7 @@ import androidx.test.espresso.ViewAssertion;
import org.junit.Assert;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DMSLocationAssertion implements ViewAssertion {
private static final String NUMBER = "(-?\\d+(?:\\.\\d*)?)";
private static final String dms_latitude_pattern = NUMBER + "°\\s*" + NUMBER + "'\\s*" + NUMBER + "\"\\s*([NS])";
private static final String dms_longitude_pattern = NUMBER + "°\\s*" + NUMBER + "'\\s*" + NUMBER + "\"\\s*([EW])";
private static final Pattern dms_latitude_regex = Pattern.compile(dms_latitude_pattern, Pattern.CASE_INSENSITIVE);
private static final Pattern dms_longitude_regex = Pattern.compile(dms_longitude_pattern, Pattern.CASE_INSENSITIVE);
private static float convertField(Matcher matcher, String name) {
float value = 0;
try {
int degrees = Integer.parseInt(Objects.requireNonNull(matcher.group(1)));
Assert.assertThat(name + " degrees", degrees, greaterThanOrEqualTo(0));
value = (float) degrees;
} catch (NumberFormatException ex) {
Assert.fail(name + " degree field not an integer");
}
try {
int minutes = Integer.parseInt(Objects.requireNonNull(matcher.group(2)));
Assert.assertThat(name + " minutes", minutes, greaterThanOrEqualTo(0));
value += (float) minutes / 60.0f;
} catch (NumberFormatException ex) {
Assert.fail(name + " minute field not an integer");
}
try {
float seconds = Float.parseFloat(Objects.requireNonNull(matcher.group(3)));
Assert.assertThat(name + " seconds", seconds, greaterThanOrEqualTo(0.0f));
value += seconds / 3600.0f;
} catch (NumberFormatException ex) {
Assert.fail(name + " seconds field not an number");
}
String direction = Objects.requireNonNull(matcher.group(4));
if (direction.equalsIgnoreCase("S") || direction.equalsIgnoreCase("W")) {
value *= -1.0f;
}
return value;
}
protected void checkCoordinates(float latitude, float longitude) {
}
@ -62,14 +20,8 @@ public class DMSLocationAssertion implements ViewAssertion {
throw noViewFoundException;
Assert.assertThat(view, instanceOf(TextView.class));
TextView text = (TextView) view;
Matcher latitude_match = dms_latitude_regex.matcher(text.getText());
Matcher longitude_match = dms_longitude_regex.matcher(text.getText());
Assert.assertTrue("Latitude not found", latitude_match.find());
Assert.assertTrue("Longitude not found", longitude_match.find());
Log.d("TAG-Map", "StrLat: " + latitude_match.group(0));
Log.d("TAG-Map", "StrLon: " + longitude_match.group(0));
float latitude = convertField(latitude_match, "Latitude");
float longitude = convertField(longitude_match, "Longitude");
float latitude = CoordinateMatcher.matchLatitude(text.getText());
float longitude = CoordinateMatcher.matchLongitude(text.getText());
checkCoordinates(latitude, longitude);
}
}

Wyświetl plik

@ -140,10 +140,10 @@ android {
jniLibs.srcDirs = ['libs']
}
androidTest {
java.srcDirs = ['androidTest/java']
java.srcDirs = ['androidTest/java', 'sharedTest/java']
}
test {
java.srcDirs = ['test/java']
java.srcDirs = ['test/java', 'sharedTest/java']
}
}
lintOptions {
@ -169,6 +169,8 @@ dependencies {
implementation 'com.squareup.okio:okio:2.1.0'
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.hamcrest:hamcrest-core:1.3'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'

Wyświetl plik

@ -0,0 +1,57 @@
package org.aprsdroid.app.testing;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import org.junit.Assert;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CoordinateMatcher {
private static final String NUMBER = "(-?\\d+(?:\\.\\d*)?)";
private static final String dms_latitude_pattern = NUMBER + "°\\s*" + NUMBER + "'\\s*" + NUMBER + "\"\\s*([NS])";
private static final String dms_longitude_pattern = NUMBER + "°\\s*" + NUMBER + "'\\s*" + NUMBER + "\"\\s*([EW])";
private static final Pattern dms_latitude_regex = Pattern.compile(dms_latitude_pattern, Pattern.CASE_INSENSITIVE);
private static final Pattern dms_longitude_regex = Pattern.compile(dms_longitude_pattern, Pattern.CASE_INSENSITIVE);
private static float convertField(CharSequence string, Pattern regex, String name) {
Matcher matcher = regex.matcher(string);
Assert.assertTrue(name + " not found", matcher.find());
float value = 0;
try {
int degrees = Integer.parseInt(Objects.requireNonNull(matcher.group(1)));
Assert.assertThat(name + " degrees", degrees, greaterThanOrEqualTo(0));
value = (float) degrees;
} catch (NumberFormatException ex) {
Assert.fail(name + " degree field not an integer");
}
try {
int minutes = Integer.parseInt(Objects.requireNonNull(matcher.group(2)));
Assert.assertThat(name + " minutes", minutes, greaterThanOrEqualTo(0));
value += (float) minutes / 60.0f;
} catch (NumberFormatException ex) {
Assert.fail(name + " minute field not an integer");
}
try {
float seconds = Float.parseFloat(Objects.requireNonNull(matcher.group(3)));
Assert.assertThat(name + " seconds", seconds, greaterThanOrEqualTo(0.0f));
value += seconds / 3600.0f;
} catch (NumberFormatException ex) {
Assert.fail(name + " seconds field not an number");
}
String direction = Objects.requireNonNull(matcher.group(4));
if (direction.equalsIgnoreCase("S") || direction.equalsIgnoreCase("W")) {
value *= -1.0f;
}
return value;
}
public static float matchLatitude(CharSequence string) {
return convertField(string, dms_latitude_regex, "Latitude");
}
public static float matchLongitude(CharSequence string) {
return convertField(string, dms_longitude_regex, "Longitude");
}
}

Wyświetl plik

@ -0,0 +1,53 @@
package org.aprsdroid.app;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.MatcherAssert.assertThat;
import org.aprsdroid.app.testing.CoordinateMatcher;
import org.junit.Assert;
import org.junit.Test;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CoordinateTest {
// Reference data generated from https://www.pgc.umn.edu/apps/convert/
private static final String providedNLatitude = "77° 15' 30\" N";
private static final float expectedNLatitude = 77.258333f;
private static final String providedELongitude = "164° 45' 15\" E";
private static final float expectedELongitude = 164.754167f;
private static final String providedSLatitude = "45° 30' 45\" S";
private static final float expectedSLatitude = -45.5125f;
private static final String providedWLongitude = "97° 20' 40\" W";
private static final float expectedWLongitude = -97.344444f;
@Test
public void givenDMSLatitudeInN_whenParsingString_ThenShouldMatchDecimal() {
float value = CoordinateMatcher.matchLatitude(providedNLatitude);
assertThat("Latitude", (double)value, closeTo((double)expectedNLatitude, 1e-7));
}
@Test
public void givenDMSLongitudeInE_whenParsingString_ThenShouldMatchDecimal() {
float value = CoordinateMatcher.matchLongitude(providedELongitude);
assertThat("Longitude", (double)value, closeTo((double)expectedELongitude, 1e-7));
}
@Test
public void givenDMSLatitudeInS_whenParsingString_ThenShouldMatchDecimal() {
float value = CoordinateMatcher.matchLatitude(providedSLatitude);
assertThat("Latitude", (double)value, closeTo((double)expectedSLatitude, 1e-7));
}
@Test
public void givenDMSLongitudeInW_whenParsingString_ThenShouldMatchDecimal() {
float value = CoordinateMatcher.matchLongitude(providedWLongitude);
assertThat("Longitude", (double)value, closeTo((double)expectedWLongitude, 1e-7));
}
}