/* CityTester.java * Csu370 :: 01/12/2008 * Test Program for 'City'; Assignment #1 */ import java.util.Random; /* A program to perform Black Box testing of the City class * In later assignments you may be asked to write a Test program * much like this, so you should review any of the concepts * used here that are not familiar to you. Or ask a TA * or Professor if you are otherwised confused. */ public class CityTester { /** Main method. After compiling it can be run with: java CityTester * Or imported into eclipse */ public static void main(String[] args){ /* Create a new Tester, run the tests, and Print out the results. */ CityTester t = new CityTester(); t.testCities(); //create some City objects and test them t.testExceptions(); //see if exceptions are thrown that should be /* A few Stats... */ System.out.println("\nNumber of cities tested: " + t.totCities); System.out.println("Number of tests performed: " + t.ntests); System.out.println("Number of errors found: " + t.nerr); } /* Variables which will track the progress of out Tests */ private int ntests = 0; // Total Tests Run private int nerr = 0; // Number of Errors /* Number of dots to print before we go to the next line */ private static final int DOTS_PER_LINE = 50; /* Update the test counters based on the result given. Result * is expected to be true for passing tests, and false for * failing tests. If a test fails, we print out the provided * message so the user can see what might have gone wrong. * Be sure to review anything that doesn't make sense. */ private void assertTrue (boolean result, String msg){ ntests++; if(!result){ System.out.println("\n**ERROR**: test# " + ntests + " -- " + msg); nerr ++; } if(ntests % DOTS_PER_LINE == 0)System.out.println(); System.out.print("."); } /* Variables that will track the totals for cities, population, northmost city, and southmost city in order to check the static methods */ private int totCities = 0; // Number of Classrooms Created private int totPop = 0; // Total Population private String northMost = null; // Northmost city private String southMost = null; // Southmost city private double northMostLatitude = 0; private double southMostLatitude = 0; /* How Many Cities to Create? */ private static final int NUM_TO_TEST = 20; private void testCities(){ // create a city which will be the base city to be compared with // the other cities, and update the "global" variables City base = City.basic("Cambridge", 500000, 45, 75); northMostLatitude = 45; southMostLatitude = 45; northMost = "Cambridge"; southMost = "Cambridge"; totCities++; totPop += 500000; Random r = new Random(); /* Create random Cities, and Test them */ for(int i = 0; i < NUM_TO_TEST; i++){ String name = "City #" + i; boolean b = r.nextInt(10) >= 5; String state = b ? "State #" + i : null; int pop = r.nextInt(1000000) + 1; double latitude = b ? r.nextDouble() * 90 : r.nextDouble() * (-90); double longitude = b ? r.nextDouble() * 180 : r.nextDouble() * (-180); /* Create the City object and test it */ testCity(name, state, pop, latitude, longitude, base); } /* Create "border case" Cities and test them */ testCity("Boston", "MA", 600000, -90, -180, base); testCity("Boston", "MA", 600000, -90, 180, base); testCity("Boston", "MA", 600000, 90, -180, base); testCity("Boston", "MA", 600000, 90, 180, base); testCity("Malta", null, 1, 0, 90, base); testCity("Juneau", "Alaska", 77777, 90, 0, base); } /* Test a single City, including static methods */ private void testCity(String name, String state, int pop, double latitude, double longitude, City base) { try{ //create the object to be tested City c; String capstr = ""; if (state != null) { c = City.capital(name, state, pop, latitude, longitude); capstr = "is the capital of " + state + ", it"; } else c = City.basic(name, pop, latitude, longitude); /* Update the numbers for our static method checks later*/ // update the northmost and southmost longitude if necessary if (latitude > northMostLatitude) { northMostLatitude = latitude; northMost = name; } if (latitude < southMostLatitude) { southMostLatitude = latitude; southMost = name; } totCities++; totPop += pop; /* Check each of the accessor methods */ assertTrue(c.getName().equals(name), "getName()"); assertTrue(c.getPopulation() == pop, "getPopulation()"); assertTrue(c.getLatitude() == latitude, "getLatitude()"); assertTrue(c.getLongitude() == longitude, "getLongitude()"); if (state != null) { assertTrue(c.capitalOf().equals(state), "capitalOf()"); assertTrue(c.isCapital(), "isCapital()"); } else { assertTrue(! c.isCapital(), "isCapital()"); } // northSouthDist double expected = 69.17 * Math.abs(c.getLatitude() - base.getLatitude()); double real = c.northSouthDist(base); assertTrue(closeEnough(expected, real), "northSouthDist()"); // eastWestDist double diff = Math.abs(c.getLongitude() - base.getLongitude()); diff = (diff <= 180) ? diff : (360 - diff); expected = diff * 69.17 * Math.cos(c.getLatitude() * Math.PI / 180); real = c.eastWestDist(base); assertTrue(closeEnough(expected, real), "eastWestDist()"); // isLarger boolean b; b = (c.getPopulation() > base.getPopulation()) ? true : false; assertTrue(b == c.isLarger(base), "isLarger()"); // toString() String expectedStr = name + capstr + " has population " + pop + " and is located at [" + latitude + ", " + longitude + "]"; assertTrue(c.toString().equals(expectedStr), "toString()"); /* Test the static methods for each City */ testStaticMethods(); } catch(RuntimeException e){ /* If there was an exception anywhere in there, then we * have a problem */ assertTrue(false, "Exception: "+e.getMessage()); } } /* Safe test for floating-point numbers. Sometimes due to rounding/ * arithmetic ordering it's possible to get two different results * for the same mathematical expression. I'm assuming here that * we will be at least within 1/10000 th of each other. */ private static boolean closeEnough(double a, double b) { return ((Math.abs(a-b)) < 0.0001); } /* Make sure each of the static methods agrees with our number (and * the specifications). */ private void testStaticMethods(){ assertTrue(City.cityCount() == totCities, "City.cityCount()"); assertTrue(City.populationTotal() == totPop, "City.populationTotal()"); assertTrue(City.northMost().equals(northMost), "City.northMost()"); assertTrue(City.southMost().equals(southMost), "City.southMost()"); } /* Make sure exceptions are thrown for border cases. * Review try{...}catch(...){...} * if this looks fishy, or ask your friendly TA ;) */ /* We make sure that good tests get counted by using: * assertTrue(true,""); * and force bad tests to fail with: * assertTrue(false,"Failure Message"); * making sure that we test both the basic and capital * static creators. */ private void testExceptions(){ /* latitude < -90 */ try{ if (City.basic("Boston", 600000, -91, 75) != null) assertTrue (false, "[basic] No Exception with latitude < -90"); } catch(RuntimeException e){ assertTrue (true, ""); } /* latitude > 90 */ try{ if (City.basic("Boston", 600000, 105, 75) != null) assertTrue (false, "[basic] No Exception with latitude > 90"); } catch(RuntimeException e){ assertTrue (true, ""); } /* longitude < -180 */ try{ if (City.basic("Boston", 600000, 50, -181) != null) assertTrue (false, "[basic] No Exception with longitude < -180"); } catch(RuntimeException e){ assertTrue (true, ""); } /* longitude > 180 */ try{ if (City.basic("Boston", 600000, 50, 250) != null) assertTrue (false, "[basic] No Exception with longitude > 180"); } catch(RuntimeException e){ assertTrue (true, ""); } /* latitude < -90 */ try{ if (City.capital("Boston", "MA", 600000, -91, 75) != null) assertTrue (false, "[capital] No Exception with latitude < -90"); } catch(RuntimeException e){ assertTrue (true, ""); } /* latitude > 90 */ try{ if (City.capital("Boston", "MA", 600000, 105, 75) != null) assertTrue (false, "[capital] No Exception with latitude > 90"); } catch(RuntimeException e){ assertTrue (true, ""); } /* longitude < -180 */ try{ if (City.capital("Boston", "MA", 600000, 50, -181) != null) assertTrue (false, "[capital] No Exception with longitude < -180"); } catch(RuntimeException e){ assertTrue (true, ""); } /* longitude > 180 */ try{ // if (City.capital("Boston", "MA", 600000, 50, 250) != null) City.capital("Boston", "MA", 600000, 50, 250); assertTrue (false, "[capital] No Exception with longitude > 180"); } catch(RuntimeException e){ assertTrue (true, ""); } /* call capitalOf() on a city which isn't a capital */ try{ City.basic("Cambridge", 500000, 50, 140).capitalOf(); assertTrue (false, "[basic] No Exception with calling capitalOf() " + "on a non-capital city"); } catch(RuntimeException e){ assertTrue (true, ""); } } }