Menu

Two new proposed matchers

Anonymous
2005-06-14
2013-04-25
  • Anonymous

    Anonymous - 2005-06-14

    I've written two matchers for my own use that others might find useful.

    The first is a SignificantDigitMatcher that only cares about floating point values up to a certain number of digits.  This is especially useful given the variability in how floats are displayed, especially if you're using copy-paste from a GUI to generate test scripts.

    The second is a ForgivingNullMatcher that is, well, 'forgiving' about the way you represent NULLs in your test script.  Again especially useful if you're using copy-paste from a GUI to generate test scripts.

    I'll try to copy the code inline below, but will also email them to the maintainers:
    /*
    * $Id: ForgivingNullMatcher.java,v 1.0 2005/06/14 19:15:45 spal Exp $
    * $Source: /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/ForgivingNullMatcher.java,v $
    * SQLUnit - a test harness for unit testing database stored procedures.
    * Copyright (C) 2003  The SQLUnit Team
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * as published by the Free Software Foundation; either version 2
    * of the License, or (at your option) any later version.
    *
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details.
    *
    * You should have received a copy of the GNU General Public License
    * along with this program; if not, write to the Free Software
    * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    */

    package net.sourceforge.sqlunit.matchers;

    import java.util.Map;

    import net.sourceforge.sqlunit.IMatcher;
    import net.sourceforge.sqlunit.SQLUnitException;

    /**
    * The ForgivingNullMatcher is an implementation of the IMatcher interface
    * used to compare values you know are either supposed to be NULL (but might be textually
    * represented differently) or are actually equal.  Basically searches for
    * the word NULL (case insensitive) or for blank elements or for elements that are
    * equal Strings.  Especially useful when you're generating your test script
    * by copying and pasting out of a SQL query tool that displays NULLs differently
    * than SQLUnit pulls back from the database.
    *
    * For example, all of these values are treated as equal:
    *
    *     <col id="14" name="proxy_for_benchcode" type="INTEGER">[NULL]</col>
    *     <col id="14" name="proxy_for_benchcode" type="INTEGER">NULL</col>
    *     <col id="14" name="proxy_for_benchcode" type="INTEGER"></col>
    *     <col id="14" name="proxy_for_benchcode" type="INTEGER">null</col>
    *
    * Example configuration:
    *     <match resultset-id="1" row-id="*" col-id="14"
          matcher="net.sourceforge.sqlunit.matchers.ForgivingNullMatcher">
      </match>
     
    * @author Tim Cull (trcull@yahoo.com)
    * @version $Revision: 1.0 $
    */
    public class ForgivingNullMatcher implements IMatcher {

        public static final String NULL_STRING = "NULL";
        /**
         *
         */
        public ForgivingNullMatcher() {
            super();
        }

           /**
         * Returns true if the value of the target and the source
         * are equivalent to NULL (either by being empty or by containing the word NULL)
         * or are actually equal to each other
         * @param source the String representing the source to be matched.
         * @param target the String representing the target to be matched.
         * @param args a Map of name value pairs of arguments passed in.
         * @return true if the matching strategy resulted in success.
         * @exception SQLUnitException if there was a problem with matching.
         */
        public boolean isEqual(String source, String target, Map args)
                throws SQLUnitException {
           
            int iSourceLength = source.length();
            int iTargetLength = target.length();
            boolean retVal = false;
            if (iSourceLength==0 && iTargetLength==0){//both are empty
                retVal = true;
            } else if (iSourceLength==0){//only source is empty
                target = target.toUpperCase();//eliminate effect of case
                if(target.indexOf(NULL_STRING)>-1){
                    retVal = true;
                }
            } else if (iTargetLength==0){//only target is empty
                source = source.toUpperCase();//eliminate effect of case
                if(source.indexOf(NULL_STRING)>-1){
                    retVal = true;
                }
            } else {//neither is empty
                if (source.equals(target)){ //either they're both actually equal, or they're both the same textual representation of NULL
                    retVal = true;
                } else { //they're not exactly equal, but might still be different textual representations of NULL
                    source = source.toUpperCase();
                    target = target.toUpperCase();
                    if(target.indexOf(NULL_STRING)>-1 && source.indexOf(NULL_STRING)>-1){
                        retVal = true;
                    }
                }
            }
            return retVal;
        }

    }

    /*
    * $Id: SignificantDigitsMatcher.java,v 1.0 2005/06/14 19:15:45 spal Exp $
    * $Source: /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/SignificantDigitsMatcher.java,v $
    * SQLUnit - a test harness for unit testing database stored procedures.
    * Copyright (C) 2003  The SQLUnit Team
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * as published by the Free Software Foundation; either version 2
    * of the License, or (at your option) any later version.
    *
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details.
    *
    * You should have received a copy of the GNU General Public License
    * along with this program; if not, write to the Free Software
    * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    */
    package net.sourceforge.sqlunit.matchers;

    import java.math.BigDecimal;
    import java.util.Map;

    import net.sourceforge.sqlunit.IErrorCodes;
    import net.sourceforge.sqlunit.IMatcher;
    import net.sourceforge.sqlunit.SQLUnitException;

    /**
    * The SignificantDigitsMatcher is an implementation of the IMatcher interface
    * used to compare FLOAT values where you only really care about matching to a certain
    * number of significant digits to the right of the decimal.  Especially useful when
    * you're generating your test script by copying and pasting out of a SQL query tool
    * that displays a different number of significant
    * digits than SQLUnit pulls back from the database.
    *
    * Example configuration:
    *     <match resultset-id="1" row-id="*" col-id="9-13,15-18"
          matcher="net.sourceforge.sqlunit.matchers.SignificantDigitsMatcher">
          <arg name="signif-digits" value="3" />
      </match>
    * @sqlunit.matcher.arg name="signif-digits"
    *  description="Number of significant digits to match to"
    * @author Tim Cull (trcull@yahoo.com)
    * @version $Revision: 1.0 $
    */
    public class SignificantDigitsMatcher implements IMatcher {

        /**
         *
         */
        public SignificantDigitsMatcher() {
            super();
        }

           /**
         * Returns true if the value of the target is equal to the source
         * up to a certain number of significant digits.
         * @param source the String representing the source to be matched.
         * @param target the String representing the target to be matched.
         * @param args a Map of name value pairs of arguments passed in.
         * @return true if the matching strategy resulted in success.
         * @exception SQLUnitException if there was a problem with matching.
         */
        public boolean isEqual(String source, String target, Map args)
                throws SQLUnitException {

            String aDigits = (String) args.get("signif-digits");
            if (aDigits == null) {
                throw new SQLUnitException(IErrorCodes.MATCHER_EXCEPTION,
                    new String[] {this.getClass().getName(),
                    "Value for key 'signif-digits' is NULL"});
            }
            // is digits an integer?
            int iDigits = 0;
            try {
                iDigits = Integer.parseInt(aDigits);
            } catch (NumberFormatException e) {
                throw new SQLUnitException(IErrorCodes.MATCHER_EXCEPTION,
                    new String[] {this.getClass().getName(),
                    "Value of key 'signif-digits' is not an INT"});
            }
            // cannot have the digits less than 0
            if (iDigits < 0) {
                throw new SQLUnitException(IErrorCodes.MATCHER_EXCEPTION,
                    new String[] {this.getClass().getName(),
                    "Value of key 'signif-digits' must be greater than or equal to zero"});
            }
            // is the source a float?
            BigDecimal dSource;
            try {
               
                dSource = new BigDecimal(source);
            } catch (NumberFormatException e) {
                throw new SQLUnitException(IErrorCodes.MATCHER_EXCEPTION,
                    new String[] {this.getClass().getName(),
                    "Value of 'source' is not a FLOAT"});
            }
            // is the target a float?
            BigDecimal dTarget;
            try {
                dTarget = new BigDecimal(target);
            } catch (NumberFormatException e) {
                throw new SQLUnitException(IErrorCodes.MATCHER_EXCEPTION,
                    new String[] {this.getClass().getName(),
                    "Value of 'target' is not a FLOAT"});
            }
           
            //convert source to a BigDecimal with right number of decimal places
            dSource = dSource.setScale(iDigits,BigDecimal.ROUND_HALF_UP );
           
            //convert target to a BigDecimal with right number of decimal places
           
            dTarget = dTarget.setScale(iDigits,BigDecimal.ROUND_HALF_UP);
           
            System.out.println("comparing " + dTarget + "("+target+") and " + dSource + "("+source+"): "+dSource.equals(dTarget));
            // return the match
            return dSource.equals(dTarget);
        }

    }

     
    • Anonymous

      Anonymous - 2005-06-14

      ps.  SourceForge took all the indentation out of my code.  I promise I don't write code that ugly in reality.

       
    • Sujit Pal

      Sujit Pal - 2005-07-13

      Hi Tim,

      > I promise I don't write code that ugly in reality.
      :-)

      Thanks again for your contributions and they are in CVS now. Heres the commit log.

      RCS file: /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/ForgivingNullMatcher.java,v
      done
      Checking in src/net/sourceforge/sqlunit/matchers/ForgivingNullMatcher.java;
      /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/ForgivingNullMatcher.java,v  <--  ForgivingNullMatcher.java
      initial revision: 1.1
      done
      RCS file: /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/SignificantDigitsMatcher.java,v
      done
      Checking in src/net/sourceforge/sqlunit/matchers/SignificantDigitsMatcher.java;
      /cvsroot/sqlunit/sqlunit/src/net/sourceforge/sqlunit/matchers/SignificantDigitsMatcher.java,v  <--  SignificantDigitsMatcher.java
      initial revision: 1.1
      done

      -sujit

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.