Tests: added many verify tests for sets and cards, e.g.:

* check set's class name/file (source code style);
  * check set's hasBasicLands settings (missing lands in deck generation bug);
  * check card's UsesVariousArt settings (same image for multi-images card bug);
  * check card's missing abilities (forgot addAbility call bug);
  * improved output messages;
This commit is contained in:
Oleg Agafonov 2018-10-03 22:32:52 +04:00
parent 64721675f2
commit 6bb478c342
2 changed files with 181 additions and 34 deletions

View file

@ -152,6 +152,30 @@ public class BoosterGenerationTest extends MageTestBase {
} }
} }
@Test
public void testColdSnap_BoosterMustHaveOneSnowLand() {
for (int i = 0; i < 10; i++) {
List<Card> booster = Coldsnap.getInstance().createBooster();
assertTrue("coldsnap's booster must contain 1 snow covered land", booster.stream().anyMatch(card -> card.isBasic() && card.getName().startsWith("Snow-Covered ")));
}
}
@Test
public void testMastersEditionII_BoosterMustHaveOneSnowLand() {
for (int i = 0; i < 10; i++) {
List<Card> booster = MastersEditionII.getInstance().createBooster();
assertTrue("Master Editions II's booster must contain 1 snow covered land", booster.stream().anyMatch(card -> card.isBasic() && card.getName().startsWith("Snow-Covered ")));
}
}
@Test
public void testBattlebond_BoosterMustHaveOneLand() {
for (int i = 0; i < 10; i++) {
List<Card> booster = Coldsnap.getInstance().createBooster();
assertTrue("battlebond's booster must contain 1 land", booster.stream().anyMatch(card -> card.isBasic() && card.isLand()));
}
}
private static String str(List<Card> cards) { private static String str(List<Card> cards) {
StringBuilder sb = new StringBuilder("["); StringBuilder sb = new StringBuilder("[");
Iterator<Card> iterator = cards.iterator(); Iterator<Card> iterator = cards.iterator();

View file

@ -4,10 +4,12 @@ import mage.ObjectColor;
import mage.cards.*; import mage.cards.*;
import mage.cards.basiclands.BasicLand; import mage.cards.basiclands.BasicLand;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Constants;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.game.permanent.token.Token; import mage.game.permanent.token.Token;
import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.TokenImpl;
import mage.util.CardUtil;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -42,12 +44,12 @@ public class VerifyCardDataTest {
skipCheckLists.put(listName, new LinkedHashSet<>()); skipCheckLists.put(listName, new LinkedHashSet<>());
} }
private static void skipListAddName(String listName, String name) { private static void skipListAddName(String listName, String set, String name) {
skipCheckLists.get(listName).add(name); skipCheckLists.get(listName).add(set + " - " + name);
} }
private static boolean skipListHaveName(String listName, String name) { private static boolean skipListHaveName(String listName, String set, String name) {
return skipCheckLists.get(listName).contains(name); return skipCheckLists.get(listName).contains(set + " - " + name);
} }
static { static {
@ -55,8 +57,8 @@ public class VerifyCardDataTest {
// power-toughness // power-toughness
skipListCreate("PT"); skipListCreate("PT");
skipListAddName("PT", "Garbage Elemental"); // UST skipListAddName("PT", "UST", "Garbage Elemental");
skipListAddName("PT", "Infinity Elemental"); // UST skipListAddName("PT", "UST", "Infinity Elemental");
// color // color
skipListCreate("COLOR"); skipListCreate("COLOR");
@ -96,15 +98,16 @@ public class VerifyCardDataTest {
} }
private void warn(Card card, String message) { private void warn(Card card, String message) {
System.out.println("Warning: " + message + " for " + card.getName() + " (" + card.getExpansionSetCode() + ")"); outputMessages.add("Warning: " + message + " for " + card.getExpansionSetCode() + " - " + card.getName() + " - " + card.getCardNumber());
} }
private void fail(Card card, String category, String message) { private void fail(Card card, String category, String message) {
failed++; failed++;
System.out.println("Error: (" + category + ") " + message + " for " + card.getName() + " (" + card.getExpansionSetCode() + ")"); outputMessages.add("Error: (" + category + ") " + message + " for " + card.getExpansionSetCode() + " - " + card.getName() + " - " + card.getCardNumber());
} }
private int failed = 0; private int failed = 0;
private ArrayList<String> outputMessages = new ArrayList<>();
@Test @Test
public void verifyCards() throws IOException { public void verifyCards() throws IOException {
@ -117,8 +120,10 @@ public class VerifyCardDataTest {
check(card, tokens); check(card, tokens);
} }
} }
printMessages(outputMessages);
if (failed > 0) { if (failed > 0) {
Assert.fail(failed + " Errors"); Assert.fail(failed + " errors in verify");
} }
} }
@ -256,12 +261,22 @@ public class VerifyCardDataTest {
} }
} }
private void printMessages(Collection<String> list) { private void printMessages(Collection<String> list, boolean sorted) {
for (String mes : list) {
ArrayList<String> sortedList = new ArrayList<>(list);
if (sorted) {
sortedList.sort(String::compareTo);
}
for (String mes : sortedList) {
System.out.println(mes); System.out.println(mes);
} }
} }
private void printMessages(Collection<String> list) {
printMessages(list, true);
}
private String extractShortClass(Class<? extends TokenImpl> tokenClass) { private String extractShortClass(Class<? extends TokenImpl> tokenClass) {
String origin = tokenClass.getName(); String origin = tokenClass.getName();
if (origin.contains("$")) { if (origin.contains("$")) {
@ -273,6 +288,114 @@ public class VerifyCardDataTest {
} }
} }
@Test
public void checkMissingSetData() {
Collection<String> errorsList = new ArrayList<>();
Collection<String> warningsList = new ArrayList<>();
Collection<ExpansionSet> sets = Sets.getInstance().values();
// 1. wrong set class names
for (ExpansionSet set : sets) {
String className = extractShortClass(set.getClass());
String needClassName = set.getName()
//.replaceAll("Duel Decks", "")
.replaceAll("&", "And")
.replaceAll(" vs. ", " Vs ") // for more friendly class name generation in logs TODO: replace to CamelCase transform instead custom words
.replaceAll(" the ", " The ")
.replaceAll(" and ", " And ")
.replaceAll(" of ", " Of ")
.replaceAll(" to ", " To ")
.replaceAll(" for ", " For ")
.replaceAll(" into ", " Into ")
.replaceAll(" over ", " Over ")
.replaceAll("[ .+-/:\"']", "");
//if (!className.toLowerCase(Locale.ENGLISH).equals(needClassName.toLowerCase(Locale.ENGLISH))) {
if (!className.equals(needClassName)) {
errorsList.add("error, set's class name must be equal to set name: "
+ className + " from " + set.getClass().getName() + ", caption: " + set.getName() + ", need name: " + needClassName);
}
}
// 2. wrong basic lands settings (it's for lands search, not booster construct)
Map<String, Boolean> skipLandCheck = new HashMap<>();
for (ExpansionSet set : sets) {
if (skipLandCheck.containsKey(set.getName())) {
continue;
}
Boolean needLand = set.hasBasicLands();
Boolean foundedLand = false;
Map<String, Integer> foundLandsList = new HashMap<>();
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
if (isBasicLandName(card.getName())) {
foundedLand = true;
int count = foundLandsList.getOrDefault(card.getName(), 0);
foundLandsList.put(card.getName(), count + 1);
}
}
String landNames = foundLandsList.entrySet().stream()
.map(p -> (p.getKey() + " - " + p.getValue().toString()))
.sorted().collect(Collectors.joining(", "));
if (needLand && !foundedLand) {
errorsList.add("error, found set with wrong hasBasicLands - it's true, but haven't land cards: " + set.getCode() + " in " + set.getClass().getName());
}
if (!needLand && foundedLand) {
errorsList.add("error, found set with wrong hasBasicLands - it's false, but have land cards: " + set.getCode() + " in " + set.getClass().getName() + ", lands: " + landNames);
}
// TODO: add test to check num cards (hasBasicLands and numLand > 0)
}
// TODO: add test to check num cards for rarity (rarityStats > 0 and numRarity > 0)
printMessages(warningsList);
printMessages(errorsList);
if (errorsList.size() > 0) {
Assert.fail("Founded set errors: " + errorsList.size());
}
}
@Test
public void checkMissingCardData() {
Collection<String> errorsList = new ArrayList<>();
Collection<String> warningsList = new ArrayList<>();
Collection<ExpansionSet> sets = Sets.getInstance().values();
// 1. wrong UsesVariousArt settings (set have duplicated card name without that setting -- e.g. cards will have same image)
for (ExpansionSet set : sets) {
// double names
Map<String, Integer> doubleNames = new HashMap<>();
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
int count = doubleNames.getOrDefault(card.getName(), 0);
doubleNames.put(card.getName(), count + 1);
}
// check
for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) {
boolean cardHaveDoubleName = (doubleNames.getOrDefault(card.getName(), 0) > 1);
boolean cardHaveVariousSetting = card.getGraphicInfo() == null ? false : card.getGraphicInfo().getUsesVariousArt();
if(cardHaveDoubleName && !cardHaveVariousSetting) {
errorsList.add("error, founded double card names, but UsesVariousArt is not true: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber());
}
}
}
printMessages(warningsList);
printMessages(errorsList);
if (errorsList.size() > 0) {
Assert.fail("Founded card errors: " + errorsList.size());
}
}
@Test @Test
@Ignore // TODO: enable test after massive token fixes @Ignore // TODO: enable test after massive token fixes
public void checkMissingTokenData() { public void checkMissingTokenData() {
@ -440,7 +563,7 @@ public class VerifyCardDataTest {
} }
private void checkColors(Card card, JsonCard ref) { private void checkColors(Card card, JsonCard ref) {
if (skipListHaveName("COLOR", card.getName())) { if (skipListHaveName("COLOR", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -460,7 +583,7 @@ public class VerifyCardDataTest {
} }
private void checkSubtypes(Card card, JsonCard ref) { private void checkSubtypes(Card card, JsonCard ref) {
if (skipListHaveName("SUBTYPE", card.getName())) { if (skipListHaveName("SUBTYPE", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -469,7 +592,7 @@ public class VerifyCardDataTest {
// fix names (e.g. Urzas to Urza's) // fix names (e.g. Urzas to Urza's)
if (expected != null && expected.contains("Urzas")) { if (expected != null && expected.contains("Urzas")) {
expected = new ArrayList<>(expected); expected = new ArrayList<>(expected);
for (ListIterator<String> it = ((List<String>) expected).listIterator(); it.hasNext();) { for (ListIterator<String> it = ((List<String>) expected).listIterator(); it.hasNext(); ) {
if (it.next().equals("Urzas")) { if (it.next().equals("Urzas")) {
it.set("Urza's"); it.set("Urza's");
} }
@ -482,7 +605,7 @@ public class VerifyCardDataTest {
} }
private void checkSupertypes(Card card, JsonCard ref) { private void checkSupertypes(Card card, JsonCard ref) {
if (skipListHaveName("SUPERTYPE", card.getName())) { if (skipListHaveName("SUPERTYPE", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -492,23 +615,8 @@ public class VerifyCardDataTest {
} }
} }
private void checkTypes(Card card, JsonCard ref) {
if (skipListHaveName("TYPE", card.getName())) {
return;
}
Collection<String> expected = ref.types;
List<String> type = new ArrayList<>();
for (CardType cardType : card.getCardType()) {
type.add(cardType.toString());
}
if (!eqSet(type, expected)) {
fail(card, "types", type + " != " + expected);
}
}
private void checkMissingAbilities(Card card, JsonCard ref) { private void checkMissingAbilities(Card card, JsonCard ref) {
if (skipListHaveName("MISSING_ABILITIES", card.getName())) { if (skipListHaveName("MISSING_ABILITIES", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -533,6 +641,21 @@ public class VerifyCardDataTest {
} }
} }
private void checkTypes(Card card, JsonCard ref) {
if (skipListHaveName("TYPE", card.getExpansionSetCode(), card.getName())) {
return;
}
Collection<String> expected = ref.types;
List<String> type = new ArrayList<>();
for (CardType cardType : card.getCardType()) {
type.add(cardType.toString());
}
if (!eqSet(type, expected)) {
fail(card, "types", type + " != " + expected);
}
}
private static <T> boolean eqSet(Collection<T> a, Collection<T> b) { private static <T> boolean eqSet(Collection<T> a, Collection<T> b) {
if (a == null || a.isEmpty()) { if (a == null || a.isEmpty()) {
return b == null || b.isEmpty(); return b == null || b.isEmpty();
@ -541,7 +664,7 @@ public class VerifyCardDataTest {
} }
private void checkPT(Card card, JsonCard ref) { private void checkPT(Card card, JsonCard ref) {
if (skipListHaveName("PT", card.getName())) { if (skipListHaveName("PT", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -561,7 +684,7 @@ public class VerifyCardDataTest {
} }
private void checkCost(Card card, JsonCard ref) { private void checkCost(Card card, JsonCard ref) {
if (skipListHaveName("COST", card.getName())) { if (skipListHaveName("COST", card.getExpansionSetCode(), card.getName())) {
return; return;
} }
@ -579,7 +702,7 @@ public class VerifyCardDataTest {
} }
private void checkNumbers(Card card, JsonCard ref) { private void checkNumbers(Card card, JsonCard ref) {
if (skipListHaveName("NUMBER", card.getName())) { if (skipListHaveName("NUMBER", card.getExpansionSetCode(), card.getName())) {
return; return;
} }