mirror of https://github.com/tasks/tasks
Created translation tests, fixed a bunch of bugs that they uncovered.
parent
062ec7bafa
commit
d77c7ef12b
@ -0,0 +1,226 @@
|
||||
package com.todoroo.andlib.test;
|
||||
|
||||
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
/**
|
||||
* Tests translations for consistency with the default values. You must
|
||||
* extend this class and create it with your own values for strings
|
||||
* and arrays.
|
||||
*
|
||||
* @author Tim Su <tim@todoroo.com>
|
||||
*
|
||||
*/
|
||||
abstract public class TranslationTests extends TodorooTestCase {
|
||||
|
||||
// --- abstract classes
|
||||
public abstract Class<?> getStringResources();
|
||||
public abstract Class<?> getArrayResources();
|
||||
|
||||
// --- tests
|
||||
|
||||
private static final class FormatStringData {
|
||||
private static final char[] scratch = new char[10];
|
||||
|
||||
/** format characters */
|
||||
public final char[] characters;
|
||||
|
||||
/** the original string */
|
||||
public final String string;
|
||||
|
||||
public FormatStringData(String string) {
|
||||
this.string = string;
|
||||
|
||||
int pos = -1;
|
||||
int count = 0;
|
||||
while(true) {
|
||||
pos = string.indexOf('%', ++pos);
|
||||
if(pos++ == -1)
|
||||
break;
|
||||
if(pos >= string.length())
|
||||
scratch[count++] = '\0';
|
||||
else
|
||||
scratch[count++] = string.charAt(pos);
|
||||
}
|
||||
characters = new char[count];
|
||||
for(int i = 0; i < count; i++) {
|
||||
characters[i] = scratch[i];
|
||||
}
|
||||
}
|
||||
|
||||
/** test that the characters match */
|
||||
public boolean matches(FormatStringData other) {
|
||||
return Arrays.equals(characters, other.characters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder value = new StringBuilder("[");
|
||||
for(int i = 0; i < characters.length; i++) {
|
||||
value.append(characters[i]);
|
||||
if(i < characters.length - 1)
|
||||
value.append(',');
|
||||
}
|
||||
value.append("]: '").append(string).append('\'');
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal test of format string parser
|
||||
*/
|
||||
public void testFormatStringParser() {
|
||||
String s = "abc";
|
||||
FormatStringData data = new FormatStringData(s);
|
||||
assertEquals(s, data.string);
|
||||
assertEquals(0, data.characters.length);
|
||||
|
||||
s = "abc %s def";
|
||||
data = new FormatStringData(s);
|
||||
assertEquals(1, data.characters.length);
|
||||
assertEquals('s', data.characters[0]);
|
||||
|
||||
s = "abc %%s def %d";
|
||||
data = new FormatStringData(s);
|
||||
assertEquals(2, data.characters.length);
|
||||
assertEquals('%', data.characters[0]);
|
||||
assertEquals('d', data.characters[1]);
|
||||
assertTrue(data.toString(), data.toString().contains("[%"));
|
||||
assertTrue(data.toString(), data.toString().contains("d]"));
|
||||
assertTrue(data.toString(), data.toString().contains(s));
|
||||
assertTrue(data.matches(new FormatStringData("espanol %% und %d si")));
|
||||
assertFalse(data.matches(new FormatStringData("ingles %d ja %% pon")));
|
||||
|
||||
s = "% abc %";
|
||||
data = new FormatStringData(s);
|
||||
assertEquals(2, data.characters.length);
|
||||
assertEquals(' ', data.characters[0]);
|
||||
assertEquals('\0', data.characters[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the format specifiers in translations match exactly the
|
||||
* translations in the default text
|
||||
*/
|
||||
public void testFormatStringsMatch() throws Exception {
|
||||
final Resources r = getContext().getResources();
|
||||
final int[] strings = getResourceIds(getStringResources());
|
||||
final FormatStringData[] formatStrings = new FormatStringData[strings.length];
|
||||
|
||||
for(int i = 0; i < strings.length; i++) {
|
||||
String string = r.getString(strings[i]);
|
||||
formatStrings[i] = new FormatStringData(string);
|
||||
}
|
||||
|
||||
final StringBuilder failures = new StringBuilder();
|
||||
|
||||
forEachLocale(new Runnable() {
|
||||
public void run() {
|
||||
Locale locale = r.getConfiguration().locale;
|
||||
for(int i = 0; i < strings.length; i++) {
|
||||
try {
|
||||
String string = r.getString(strings[i]);
|
||||
FormatStringData newFS = new FormatStringData(string);
|
||||
if(!newFS.matches(formatStrings[i])) {
|
||||
String name = r.getResourceName(strings[i]);
|
||||
failures.append(String.format("%s (%s): %s != %s\n",
|
||||
name, locale.toString(), newFS, formatStrings[i]));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
String name = r.getResourceName(strings[i]);
|
||||
failures.append(String.format("%s: error opening %s: %s\n",
|
||||
locale.toString(), name, e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(failures.toString(), 0, failures.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that there are the same number of array entries in each locale
|
||||
*/
|
||||
public void testArraySizesMatch() throws Exception {
|
||||
final Resources r = getContext().getResources();
|
||||
final int[] arrays = getResourceIds(getArrayResources());
|
||||
final int[] sizes = new int[arrays.length];
|
||||
for(int i = 0; i < arrays.length; i++) {
|
||||
sizes[i] = r.getStringArray(arrays[i]).length;
|
||||
}
|
||||
|
||||
final StringBuilder failures = new StringBuilder();
|
||||
forEachLocale(new Runnable() {
|
||||
public void run() {
|
||||
for(int i = 0; i < arrays.length; i++) {
|
||||
int size = r.getStringArray(arrays[i]).length;
|
||||
if(size != sizes[i]) {
|
||||
String name = r.getResourceName(arrays[i]);
|
||||
Locale locale = r.getConfiguration().locale;
|
||||
failures.append(String.format("%s (%s): size %d != %d\n",
|
||||
name, locale.toString(), size, sizes[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
assertEquals(failures.toString(), 0, failures.length());
|
||||
}
|
||||
|
||||
// --- helper methods
|
||||
|
||||
/**
|
||||
* @return an array of all string resource id's
|
||||
*/
|
||||
private int[] getResourceIds(Class<?> resources) throws Exception {
|
||||
Field[] fields = resources.getDeclaredFields();
|
||||
int[] ids = new int[fields.length];
|
||||
for(int i = 0; i < fields.length; i++) {
|
||||
ids[i] = fields[i].getInt(null);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through each locale and call runnable
|
||||
* @param r
|
||||
*/
|
||||
private void forEachLocale(Runnable r) {
|
||||
Locale[] locales = Locale.getAvailableLocales();
|
||||
for(Locale locale : locales) {
|
||||
setLocale(locale);
|
||||
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locale
|
||||
* @param locale
|
||||
*/
|
||||
private void setLocale(Locale locale) {
|
||||
Locale.setDefault(locale);
|
||||
Configuration config = new Configuration();
|
||||
config.locale = locale;
|
||||
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
|
||||
getContext().getResources().updateConfiguration(config, metrics);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
setLocale(Locale.getDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
setLocale(Locale.getDefault());
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.todoroo.astrid.test;
|
||||
|
||||
|
||||
|
||||
import com.timsu.astrid.R;
|
||||
import com.todoroo.andlib.test.TranslationTests;
|
||||
|
||||
public class AstridTranslationTests extends TranslationTests {
|
||||
|
||||
@Override
|
||||
public Class<?> getArrayResources() {
|
||||
return R.array.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getStringResources() {
|
||||
return R.string.class;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue