Changeset 1953


Ignore:
Timestamp:
12/20/06 16:56:51 (13 years ago)
Author:
curtis
Message:

Retool ReaderTest to avoid weird use of static variables; add comments
explaining the class's limitations within the JUnit framework.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/test/ReaderTest.java

    r1950 r1953  
    3333/** 
    3434 * JUnit tester for Bio-Formats file format readers. 
    35  * Failed tests are written to a logfile, for easier processing. 
     35 * Details on failed tests are written to a log file, for easier processing. 
     36 * 
     37 * To test the framework, run this class from the command line with a command 
     38 * line argument indicating the root path of data files to be tested. The 
     39 * path will be scanned, and a list of files to test will be built (files 
     40 * matching those enumerated in bad-files.txt are excluded). 
     41 * 
     42 * Unfortunately, it is not practical to construct one large JUnit test suite 
     43 * with a static suite() method, because many datasets are spread across 
     44 * multiple files. For example, a collection of 100 TIFF files numbered 
     45 * tiff001.tif through tiff100.tif should only be tested once, rather than 100 
     46 * times. To solve this problem, the list of files to test is whittled down 
     47 * dynamically -- after each file is tested, the Bio-Formats library reports 
     48 * all files that are part of that same dataset (i.e., essentially, a list of 
     49 * all files just tested). These files are all removed from the list, ensuring 
     50 * each dataset is only tested once. 
     51 * 
     52 * As such, this test case is not well suited for use with most JUnit tools, 
     53 * such as junit.awtui.TestRunner, junit.swingui.TestRunner, or 
     54 * junit.textui.TestRunner. If you are interested enough in unit testing to 
     55 * have read this explanation, and have any thoughts or suggestions for 
     56 * improvement, your thoughts would be most welcome. 
    3657 */ 
    3758public class ReaderTest extends TestCase { 
     
    4263  private static final boolean DEBUG = false; 
    4364 
     65  // -- Static fields -- 
     66 
     67  private static Vector badFiles; 
     68  private static FileWriter logFile; 
     69  private String[] used; 
     70 
    4471  // -- Fields -- 
    4572 
    46   private static Vector badFiles; 
    47   private static String currentFile; 
    48   private static FileStitcher reader; 
    49   private static FileWriter logFile; 
     73  private String id; 
     74  private FileStitcher reader; 
    5075 
    5176  // -- Constructor -- 
     
    5378  public ReaderTest(String s) { 
    5479    super(s); 
    55   } 
    56  
    57   // -- Static ReaderTest API methods -- 
    58  
    59   /** Makes our results available to a TestRunner. */ 
    60   public static Test suite() { 
    61     TestSuite suite = new TestSuite(); 
    62     suite.addTest(new ReaderTest("testBufferedImageDimensions")); 
    63     suite.addTest(new ReaderTest("testByteArrayDimensions")); 
    64     suite.addTest(new ReaderTest("testImageCount")); 
    65     suite.addTest(new ReaderTest("testOMEXML")); 
    66     return suite; 
    67   } 
    68  
    69   /** Sets the file to process. */ 
    70   public static void setFile(String file) { 
    71     currentFile = file; 
    72   } 
    73  
    74   /** 
    75    * Determines if the given filename is a "bad" file. 
    76    * Bad files are skipped rather than tested. 
    77    */ 
    78   public static boolean isBadFile(String file) { 
    79     if (badFiles == null) { 
    80       try { 
    81         badFiles = new Vector(); 
    82         BufferedReader in = new BufferedReader(new FileReader("bad-files.txt")); 
    83         while (true) { 
    84           String line = in.readLine(); 
    85           if (line == null) break; 
    86           badFiles.add(line); 
    87         } 
    88         in.close(); 
    89       } 
    90       catch (IOException io) { 
    91         if (DEBUG) io.printStackTrace(); 
    92       } 
    93     } 
    94     if (badFiles.contains(file)) return true; 
    95     for (int i=0; i<badFiles.size(); i++) { 
    96       if (file.endsWith((String) badFiles.get(i))) return true; 
    97     } 
    98     return false;  
    99   } 
    100  
    101   /** Resets the format reader. */ 
    102   public static void resetReader() { 
    103     if (reader != null) { 
    104       try { 
    105         reader.close(); 
    106       } 
    107       catch (Exception e) { 
    108         if (DEBUG) e.printStackTrace(); 
    109       } 
    110     } 
    111     reader = new FileStitcher(); 
    112     OMEXMLMetadataStore store = new OMEXMLMetadataStore(); 
    113     store.createRoot(); 
    114     reader.setMetadataStore(store); 
    115   } 
    116  
    117   /** Recursively generates a list of files to test. */ 
    118   public static void getFiles(String root, Vector files) { 
    119     resetReader(); 
    120     File f = new File(root); 
    121     String[] subs = f.list(); 
    122     if (subs == null) { 
    123       System.out.println("Invalid directory: " + root);  
    124       return; 
    125     } 
    126     for (int i=0; i<subs.length; i++) { 
    127       if (DEBUG) debug("Checking file " + subs[i]); 
    128       if (isBadFile(subs[i])) { 
    129         if (DEBUG) debug(subs[i] + " is a bad file"); 
    130         continue; 
    131       } 
    132       subs[i] = root + File.separator + subs[i];  
    133       if (new File(subs[i]).isDirectory()) getFiles(subs[i], files); 
    134       else { 
    135         if (reader.isThisType(subs[i])) { 
    136           if (DEBUG) debug("Adding " + subs[i]); 
    137           files.add(subs[i]); 
    138         } 
    139         else if (DEBUG) debug(subs[i] + " has invalid type"); 
    140       } 
    141     } 
    142   } 
    143  
    144   /** Writes the given message to the log file. */ 
    145   public static void writeLog(String s) { 
    146     if (logFile == null) { 
    147       Date date = new Date(); 
    148       try { 
    149         logFile = new FileWriter("bioformats-test-" + date.toString() + ".log"); 
    150         logFile.flush(); 
    151       } 
    152       catch (IOException io) { 
    153         if (DEBUG) io.printStackTrace(); 
    154       } 
    155     } 
    156     try { 
    157       logFile.write(s + "\n"); 
    158       logFile.flush(); 
    159     } 
    160     catch (IOException exc) { 
    161       if (DEBUG) exc.printStackTrace(); 
    162     } 
    163   } 
    164  
    165   public static void debug(String s) { System.out.println(s); } 
     80    throw new RuntimeException("Sorry, ReaderTest must be constructed with " + 
     81      "a filename to read for performing the tests. See the class javadoc " + 
     82      "for ReaderTest for more details."); 
     83  } 
     84 
     85  public ReaderTest(String s, String id) { 
     86    super(s); 
     87    this.id = id; 
     88  } 
     89 
     90  // -- ReaderTest API methods -- 
     91 
     92  /** Gets all constituent files in the tested dataset. */ 
     93  public String[] getUsedFiles() { return used; } 
    16694 
    16795  // -- ReaderTest API methods - tests -- 
     
    174102    boolean success = true; 
    175103    try { 
    176       for (int i=0; i<reader.getSeriesCount(currentFile); i++) { 
    177         reader.setSeries(currentFile, i); 
    178         int imageCount = reader.getImageCount(currentFile); 
    179         int sizeX = reader.getSizeX(currentFile); 
    180         int sizeY = reader.getSizeY(currentFile); 
     104      for (int i=0; i<reader.getSeriesCount(id); i++) { 
     105        reader.setSeries(id, i); 
     106        int imageCount = reader.getImageCount(id); 
     107        int sizeX = reader.getSizeX(id); 
     108        int sizeY = reader.getSizeY(id); 
    181109        for (int j=0; j<imageCount; j++) { 
    182           BufferedImage b = reader.openImage(currentFile, j); 
     110          BufferedImage b = reader.openImage(id, j); 
    183111          boolean failW = b.getWidth() != sizeX; 
    184112          boolean failH = b.getHeight() != sizeY; 
    185           if (failW) writeLog(currentFile + " failed width test"); 
    186           if (failH) writeLog(currentFile + " failed height test"); 
     113          if (failW) writeLog(id + " failed width test"); 
     114          if (failH) writeLog(id + " failed height test"); 
    187115          if (failW || failH) { 
    188116            success = false; 
    189117            j = imageCount; 
    190             i = reader.getSeriesCount(currentFile); 
     118            i = reader.getSeriesCount(id); 
    191119            break; 
    192120          } 
     
    198126      success = false;  
    199127    } 
    200     if (!success) writeLog(currentFile + " failed BufferedImage test"); 
     128    if (!success) writeLog(id + " failed BufferedImage test"); 
    201129    assertTrue(success); 
    202130  } 
     
    209137    boolean success = true; 
    210138    try { 
    211       for (int i=0; i<reader.getSeriesCount(currentFile); i++) { 
    212         reader.setSeries(currentFile, i); 
    213         int imageCount = reader.getImageCount(currentFile); 
    214         int sizeX = reader.getSizeX(currentFile); 
    215         int sizeY = reader.getSizeY(currentFile); 
     139      for (int i=0; i<reader.getSeriesCount(id); i++) { 
     140        reader.setSeries(id, i); 
     141        int imageCount = reader.getImageCount(id); 
     142        int sizeX = reader.getSizeX(id); 
     143        int sizeY = reader.getSizeY(id); 
    216144        int bytesPerPixel =  
    217           FormatReader.getBytesPerPixel(reader.getPixelType(currentFile)); 
    218         int sizeC = reader.getSizeC(currentFile); 
    219         boolean rgb = reader.isRGB(currentFile); 
     145          FormatReader.getBytesPerPixel(reader.getPixelType(id)); 
     146        int sizeC = reader.getSizeC(id); 
     147        boolean rgb = reader.isRGB(id); 
    220148 
    221149        int expectedBytes = sizeX * sizeY * bytesPerPixel * (rgb ? sizeC : 1); 
    222150 
    223151        for (int j=0; j<imageCount; j++) { 
    224           byte[] b = reader.openBytes(currentFile, j); 
     152          byte[] b = reader.openBytes(id, j); 
    225153          if (b.length != expectedBytes) { 
    226154            success = false;  
    227155            j = imageCount; 
    228             i = reader.getSeriesCount(currentFile); 
     156            i = reader.getSeriesCount(id); 
    229157            break; 
    230158          } 
     
    236164      success = false;  
    237165    } 
    238     if (!success) writeLog(currentFile + " failed byte array test"); 
     166    if (!success) writeLog(id + " failed byte array test"); 
    239167    assertTrue(success); 
    240168  } 
     
    247175    boolean success = true; 
    248176    try { 
    249       for (int i=0; i<reader.getSeriesCount(currentFile); i++) { 
    250         reader.setSeries(currentFile, i); 
    251         int imageCount = reader.getImageCount(currentFile); 
    252         int sizeZ = reader.getSizeZ(currentFile); 
    253         int sizeC = reader.getEffectiveSizeC(currentFile); 
    254         int sizeT = reader.getSizeT(currentFile); 
     177      for (int i=0; i<reader.getSeriesCount(id); i++) { 
     178        reader.setSeries(id, i); 
     179        int imageCount = reader.getImageCount(id); 
     180        int sizeZ = reader.getSizeZ(id); 
     181        int sizeC = reader.getEffectiveSizeC(id); 
     182        int sizeT = reader.getSizeT(id); 
    255183        success = imageCount == sizeZ * sizeC * sizeT; 
    256184        if (!success) { 
    257           writeLog(currentFile + " failed image count test"); 
     185          writeLog(id + " failed image count test"); 
    258186          assertTrue(false); 
    259187        } 
     
    263191    catch (Exception e) {  
    264192      if (DEBUG) e.printStackTrace(); 
    265       writeLog(currentFile + " failed image count test"); 
     193      writeLog(id + " failed image count test"); 
    266194      assertTrue(false);  
    267195    } 
     
    274202  public void testOMEXML() { 
    275203    try { 
    276       OMEXMLMetadataStore store =  
    277         (OMEXMLMetadataStore) reader.getMetadataStore(currentFile); 
    278   
     204      OMEXMLMetadataStore store = new OMEXMLMetadataStore(); 
     205      store.createRoot(); 
     206      reader.setMetadataStore(store); 
     207 
    279208      boolean success = true; 
    280       for (int i=0; i<reader.getSeries(currentFile); i++) { 
    281         reader.setSeries(currentFile, i); 
    282         int sizeX = reader.getSizeX(currentFile); 
    283         int sizeY = reader.getSizeY(currentFile); 
    284         int sizeZ = reader.getSizeZ(currentFile); 
    285         int sizeC = reader.getSizeC(currentFile); 
    286         int sizeT = reader.getSizeT(currentFile); 
    287         boolean bigEndian = !reader.isLittleEndian(currentFile); 
     209      for (int i=0; i<reader.getSeries(id); i++) { 
     210        reader.setSeries(id, i); 
     211        int sizeX = reader.getSizeX(id); 
     212        int sizeY = reader.getSizeY(id); 
     213        int sizeZ = reader.getSizeZ(id); 
     214        int sizeC = reader.getSizeC(id); 
     215        int sizeT = reader.getSizeT(id); 
     216        boolean bigEndian = !reader.isLittleEndian(id); 
    288217        String type =  
    289           FormatReader.getPixelTypeString(reader.getPixelType(currentFile)); 
    290         String dimensionOrder = reader.getDimensionOrder(currentFile); 
     218          FormatReader.getPixelTypeString(reader.getPixelType(id)); 
     219        String dimensionOrder = reader.getDimensionOrder(id); 
    291220 
    292221        Integer ii = new Integer(i); 
     
    299228        boolean failType = !type.equalsIgnoreCase(store.getPixelType(ii)); 
    300229        boolean failDE = !dimensionOrder.equals(store.getDimensionOrder(ii)); 
    301         if (failX) writeLog(currentFile + " failed OME-XML SizeX test"); 
    302         if (failY) writeLog(currentFile + " failed OME-XML SizeY test"); 
    303         if (failZ) writeLog(currentFile + " failed OME-XML SizeZ test"); 
    304         if (failC) writeLog(currentFile + " failed OME-XML SizeC test"); 
    305         if (failT) writeLog(currentFile + " failed OME-XML SizeT test"); 
    306         if (failBE) writeLog(currentFile + " failed OME-XML BigEndian test"); 
    307         if (failType) writeLog(currentFile + " failed OME-XML PixelType test"); 
     230        if (failX) writeLog(id + " failed OME-XML SizeX test"); 
     231        if (failY) writeLog(id + " failed OME-XML SizeY test"); 
     232        if (failZ) writeLog(id + " failed OME-XML SizeZ test"); 
     233        if (failC) writeLog(id + " failed OME-XML SizeC test"); 
     234        if (failT) writeLog(id + " failed OME-XML SizeT test"); 
     235        if (failBE) writeLog(id + " failed OME-XML BigEndian test"); 
     236        if (failType) writeLog(id + " failed OME-XML PixelType test"); 
    308237        if (failDE) { 
    309           writeLog(currentFile + " failed OME-XML DimensionOrder test"); 
     238          writeLog(id + " failed OME-XML DimensionOrder test"); 
    310239        } 
    311240        if (failX || failY || failZ || failC || failT || 
     
    319248    catch (Exception e) {  
    320249      if (DEBUG) e.printStackTrace(); 
    321       writeLog(currentFile + " failed OME-XML sanity test"); 
     250      writeLog(id + " failed OME-XML sanity test"); 
    322251      assertTrue(false);  
    323252    } 
     
    325254 
    326255  // -- TestCase API methods -- 
     256 
     257  /** Sets up the fixture. */ 
     258  protected void setUp() { 
     259    reader = new FileStitcher(); 
     260  } 
    327261 
    328262  /** Releases resources after tests have completed. */ 
    329263  protected void tearDown() { 
    330264    try { 
     265      used = reader.getUsedFiles(id); 
    331266      reader.close(); 
    332       badFiles = null; 
    333       if (logFile != null) { 
    334         logFile.close(); 
    335         logFile = null; 
    336       } 
    337267    } 
    338268    catch (FormatException fe) { 
     
    343273    } 
    344274  } 
     275 
     276  // -- Static ReaderTest API methods -- 
     277 
     278  /** 
     279   * Creates a test suite for all ReaderTest tests, on the given file. 
     280   * This method is patterned after the suite() method for use with a 
     281   * TestRunner, but is distinct in that ReaderTest tests must be executed 
     282   * on a particular input file. 
     283   */ 
     284  public static TestSuite suite(String id) { 
     285    TestSuite suite = new TestSuite(); 
     286    suite.addTest(new ReaderTest("testBufferedImageDimensions", id)); 
     287    suite.addTest(new ReaderTest("testByteArrayDimensions", id)); 
     288    suite.addTest(new ReaderTest("testImageCount", id)); 
     289    suite.addTest(new ReaderTest("testOMEXML", id)); 
     290    return suite; 
     291  } 
     292 
     293  /** 
     294   * Determines if the given filename is a "bad" file. 
     295   * Bad files are skipped rather than tested. 
     296   */ 
     297  public static boolean isBadFile(String file) { 
     298    if (badFiles == null) { 
     299      try { 
     300        badFiles = new Vector(); 
     301        BufferedReader in = new BufferedReader(new InputStreamReader( 
     302          ReaderTest.class.getResourceAsStream("bad-files.txt"))); 
     303        while (true) { 
     304          String line = in.readLine(); 
     305          if (line == null) break; 
     306          badFiles.add(line); 
     307        } 
     308        in.close(); 
     309      } 
     310      catch (IOException io) { 
     311        if (DEBUG) io.printStackTrace(); 
     312      } 
     313    } 
     314    String absFile = new File(file).getAbsolutePath(); 
     315    for (int i=0; i<badFiles.size(); i++) { 
     316      String bad = (String) badFiles.elementAt(i); 
     317      if (absFile.endsWith(bad)) return true; 
     318    } 
     319    return false;  
     320  } 
     321 
     322  /** Recursively generates a list of files to test. */ 
     323  public static void getFiles(String root, Vector files) { 
     324    File f = new File(root); 
     325    String[] subs = f.list(); 
     326    if (subs == null) { 
     327      System.out.println("Invalid directory: " + root);  
     328      return; 
     329    } 
     330    ImageReader ir = new ImageReader(); 
     331    for (int i=0; i<subs.length; i++) { 
     332      if (DEBUG) debug("Checking file " + subs[i]); 
     333      subs[i] = root + File.separator + subs[i];  
     334      if (isBadFile(subs[i])) { 
     335        if (DEBUG) debug(subs[i] + " is a bad file"); 
     336        continue; 
     337      } 
     338      if (new File(subs[i]).isDirectory()) getFiles(subs[i], files); 
     339      else { 
     340        if (ir.isThisType(subs[i])) { 
     341          if (DEBUG) debug("Adding " + subs[i]); 
     342          files.add(subs[i]); 
     343        } 
     344        else if (DEBUG) debug(subs[i] + " has invalid type"); 
     345      } 
     346    } 
     347  } 
     348 
     349  /** Writes the given message to the log file. */ 
     350  public static void writeLog(String s) { 
     351    if (logFile == null) { 
     352      try { 
     353        logFile = new FileWriter( 
     354          "bio-formats-test-" + new Date().toString() + ".log"); 
     355        logFile.flush(); 
     356      } 
     357      catch (IOException io) { 
     358        if (DEBUG) io.printStackTrace(); 
     359      } 
     360    } 
     361    try { 
     362      logFile.write(s + "\n"); 
     363      logFile.flush(); 
     364    } 
     365    catch (IOException exc) { 
     366      if (DEBUG) exc.printStackTrace(); 
     367    } 
     368  } 
     369 
     370  public static void debug(String s) { System.out.println(s); } 
    345371 
    346372  // -- Main method -- 
     
    358384    getFiles(args[0], files); 
    359385    System.out.println(files.size() + " found."); 
     386    FileStitcher stitcher = new FileStitcher(); 
    360387    while (files.size() > 0) { 
    361       String file = (String) files.get(0); 
     388      String id = (String) files.get(0); 
    362389      try { 
    363         FilePattern fp = reader.getFilePattern(file); 
     390        FilePattern fp = stitcher.getFilePattern(id); 
    364391        System.out.println("Testing " + fp.getPattern()); 
    365392      } 
    366393      catch (FormatException exc) { exc.printStackTrace(); } 
    367394      catch (IOException exc) { exc.printStackTrace(); } 
    368       setFile(file); 
    369395      TestResult result = new TestResult(); 
    370       suite().run(result); 
     396      TestSuite suite = suite(id); 
     397      suite.run(result); 
    371398      int total = result.runCount(); 
    372399      int failed = result.failureCount(); 
    373400      float failPercent = (float) (100 * ((double) failed / (double) total)); 
    374       System.out.println(file + " - " + failed + " failures in " + 
     401      System.out.println(id + " - " + failed + " failures in " + 
    375402        total + " tests (" + failPercent + "% failed)"); 
    376403 
    377       // remove relevant files from the list 
    378       try { 
    379         String[] used = reader.getUsedFiles(file); 
    380         for (int i=0; i<used.length; i++) { 
    381           if (DEBUG) System.out.println("Removing " + used[i]); 
    382           files.removeElement(used[i]); 
    383         } 
    384       } 
    385       catch (FormatException exc) { exc.printStackTrace(); } 
    386       catch (IOException exc) { exc.printStackTrace(); } 
    387  
    388       resetReader(); 
     404      // remove files part of the just-tested dataset from the list 
     405      ReaderTest test = (ReaderTest) suite.testAt(0); 
     406      String[] used = test.getUsedFiles(); 
     407      for (int i=0; i<used.length; i++) { 
     408        if (DEBUG) System.out.println("Removing " + used[i]); 
     409        files.removeElement(used[i]); 
     410      } 
    389411    } 
    390412  } 
Note: See TracChangeset for help on using the changeset viewer.