Derby
  1. Derby
  2. DERBY-2151

"Fixer-upper" utility to help convert ij canon-based tests to JUnit.

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 10.3.1.4
    • Fix Version/s: 10.3.1.4
    • Component/s: Test
    • Labels:
      None

      Description

      As part of my work to get the XML tests running in JUnit (DERBY-1758) I had to convert the old ij test lang/xml_general.sql into a JUnit equivalent. After hand-converting about twenty or so lines of ij "master" output to the corresponding JUnit commands, I became bored with the melancholy of such a task. So I hastily threw together a small utility to help automate as much of the process as possible.

      To be perfectly frank, the utility is a shameful piece of code. It's poorly-written, non-intuitive, overly complex and not at all well thought-out. It's also completely UN-commented. I wish I could follow-up with a half-hearted claim that "at least it works", but I'm not even sure that's always true...

      My first (and still lingering) inclination is to just bury the utility and never look at it again. However, I have to admit that, while the code is a nightmare to understand, it did a) prompt me to add some general-purpose JUnit utility methods that can be useful (DERBY-1976), and b) save me a lot of time by providing a rough translation of the ij test to JUnit. Then instead of piddling away at line-by-conversions of the test I was able to spend my time re-organizing the JUnit version to make it adhere to the JUnit suggestions on the second page of:

      http://www.javaworld.com/jw-12-2000/jw-1221-junit.html

      So the utility did save me time. And for that reason I've decided to choke down my embarassment and post it to a Jira issue for other developers who may find it useful (or perhaps entertaining as an example of bad programming)...

      1. derby-2151-andrew-v1.diff
        38 kB
        Andrew McIntyre
      2. derby-2151-andrew-v2.diff
        41 kB
        Andrew McIntyre
      3. ijToJUnit.java
        36 kB
        A B
      4. skipBlankLines.diff
        1 kB
        Bryan Pendleton

        Activity

        Hide
        A B added a comment -

        Attaching the java file. The program, called "ijToJUnit", takes as input the embedded master file corresponding to a .sql test and does a line-by-line mapping of that output file to corresponding JUnit calls. Note that the master file should be the embedded master (.out) file; the tool will not work with output files generated by Derby Client or JCC tests. That said, though, the JUnit commands generated by the tool are intended to behave the same regardless of the framework in use.

        Usage: java ijToJUnit <embedded_sql_out_file>

        While processing a master file, the tool may ignore lines that it thinks are irrelevant to the test. In that case the lines will be written to the output file with the tag "[**:: IGNORED ::**]" in front of them. If the tool encounters any lines in the .out file that it does not know how to convert, it will write the lines to the output file with the tag "[**:: UNCONVERTED ::**]".

        Upon completion the tool prints out the number of lines it ignored, the number of lines it left unconverted, and the name of the output file that it generated. Theoretically, if the total number of lines ignored and unconverted is zero, the result file should be compilable as a JUnit test in Derby.


        Ex:

        > java ijToJUnit altertable.out

        ==> Ignored 0 lines and left 22 lines unconverted.
        ==> Output is in 'altertable.junit'.

        Done.


        In this case no lines were ignored but the tool left all of the "show" and "describe" commands (and corresponding output) unconverted because those are ij-specific commands and thus the mapping to JUnit is not straightforward. It is then up to the user of the tool to examine the output file and figure out what to do with the ignored/unconverted output.

        I ran the tool against a couple of the .out files in lang/ and in all cases the output had to be manually corrected in at least a couple of places before the test ran without error. So this is not a one-shot JUnit test creation tool. Once created the output will almost certainly need manual correction for formatting, long lines, or functional mis-conversions. And once that's done, the user will probably have to do a reorganization of the generated JUnit code so that it adheres to the recommended JUnit programming practices:

        http://www.javaworld.com/jw-12-2000/jw-1221-junit.html

        In particular, that link recommends small, independent test cases--but the ijToJUnit tool creates a single, large test method that encapsulates the entire .sql test. So even when the generated output has been manually fixed up to run without error, it may still need additional "good practice" changes.

        The hope is that this ijToJUnit tool can help speed up the process of converting .sql tests to JUnit tests. It is not, however, meant to be a complete solution, nor is it by any means an intelligent one. It's just the (perhaps shameful) result of a hastily written "helper" utility that began one Friday afternoon.

        Anyone interested should feel free pick it up and make it better. Or perhaps s/he will be inspired by the concept but will start from scratch and do a better job, which might be easier...

        Show
        A B added a comment - Attaching the java file. The program, called "ijToJUnit", takes as input the embedded master file corresponding to a .sql test and does a line-by-line mapping of that output file to corresponding JUnit calls. Note that the master file should be the embedded master (.out) file; the tool will not work with output files generated by Derby Client or JCC tests. That said, though, the JUnit commands generated by the tool are intended to behave the same regardless of the framework in use. Usage: java ijToJUnit <embedded_sql_out_file> While processing a master file, the tool may ignore lines that it thinks are irrelevant to the test. In that case the lines will be written to the output file with the tag " [**:: IGNORED ::**] " in front of them. If the tool encounters any lines in the .out file that it does not know how to convert, it will write the lines to the output file with the tag " [**:: UNCONVERTED ::**] ". Upon completion the tool prints out the number of lines it ignored, the number of lines it left unconverted, and the name of the output file that it generated. Theoretically, if the total number of lines ignored and unconverted is zero, the result file should be compilable as a JUnit test in Derby. Ex: > java ijToJUnit altertable.out ==> Ignored 0 lines and left 22 lines unconverted. ==> Output is in 'altertable.junit'. Done. In this case no lines were ignored but the tool left all of the "show" and "describe" commands (and corresponding output) unconverted because those are ij-specific commands and thus the mapping to JUnit is not straightforward. It is then up to the user of the tool to examine the output file and figure out what to do with the ignored/unconverted output. I ran the tool against a couple of the .out files in lang/ and in all cases the output had to be manually corrected in at least a couple of places before the test ran without error. So this is not a one-shot JUnit test creation tool. Once created the output will almost certainly need manual correction for formatting, long lines, or functional mis-conversions. And once that's done, the user will probably have to do a reorganization of the generated JUnit code so that it adheres to the recommended JUnit programming practices: http://www.javaworld.com/jw-12-2000/jw-1221-junit.html In particular, that link recommends small, independent test cases--but the ijToJUnit tool creates a single, large test method that encapsulates the entire .sql test. So even when the generated output has been manually fixed up to run without error, it may still need additional "good practice" changes. The hope is that this ijToJUnit tool can help speed up the process of converting .sql tests to JUnit tests. It is not , however, meant to be a complete solution, nor is it by any means an intelligent one. It's just the (perhaps shameful) result of a hastily written "helper" utility that began one Friday afternoon. Anyone interested should feel free pick it up and make it better. Or perhaps s/he will be inspired by the concept but will start from scratch and do a better job, which might be easier...
        Hide
        Andrew McIntyre added a comment -

        I figured I could use this to convert grantRevokeDDL/grantRevokeDDL2, so I took Army's original utility (thanks, Army!) and made a few alterations to account for multiple user connections among other things. I wasn't aiming for anything close to perfection, so I stopped when I got it to convert > 99% of the SQL in grantRevokeDDL and grantRevokeDDL2. I also put it into the functiontests.util package, so that it would compile easily with the current build setup. Attaching the updated utility, also renamed to SQLToJunit, as a diff.

        The newer version actually converts simpler tests more poorly than the original version, mostly because ij sometimes doesn't print a row count out for queries. It seems like it would be easy to hold on to a line in the rewritten getNextIjCommand() and simply push that into the buffer on the next call if the we read one too many lines and get a comment or command.

        If I have some time I'll look into fixing it up a bit more to handle a broader range of cases. It seems like in the future it might be useful for easily converting SQL provided by users into reusable JUnit testcases.

        Show
        Andrew McIntyre added a comment - I figured I could use this to convert grantRevokeDDL/grantRevokeDDL2, so I took Army's original utility (thanks, Army!) and made a few alterations to account for multiple user connections among other things. I wasn't aiming for anything close to perfection, so I stopped when I got it to convert > 99% of the SQL in grantRevokeDDL and grantRevokeDDL2. I also put it into the functiontests.util package, so that it would compile easily with the current build setup. Attaching the updated utility, also renamed to SQLToJunit, as a diff. The newer version actually converts simpler tests more poorly than the original version, mostly because ij sometimes doesn't print a row count out for queries. It seems like it would be easy to hold on to a line in the rewritten getNextIjCommand() and simply push that into the buffer on the next call if the we read one too many lines and get a comment or command. If I have some time I'll look into fixing it up a bit more to handle a broader range of cases. It seems like in the future it might be useful for easily converting SQL provided by users into reusable JUnit testcases.
        Hide
        Andrew McIntyre added a comment -

        Attaching an updated version of the last patch which includes statement push back, and detects ij's show and describe statements and marks them as unconverted. I tried this on a handful of sql and it does at least a good of a job converting them as the original patch.

        I do think this could be useful in the future as well as for the current test converrsion project, so if no one objects, I'll check this in shortly.

        Show
        Andrew McIntyre added a comment - Attaching an updated version of the last patch which includes statement push back, and detects ij's show and describe statements and marks them as unconverted. I tried this on a handful of sql and it does at least a good of a job converting them as the original patch. I do think this could be useful in the future as well as for the current test converrsion project, so if no one objects, I'll check this in shortly.
        Hide
        Andrew McIntyre added a comment -

        Committed -v2 patch with some additional comments with revision 530182

        Show
        Andrew McIntyre added a comment - Committed -v2 patch with some additional comments with revision 530182
        Hide
        A B added a comment -

        Thanks for taking the time to improve the utility, Andrew. I know it wasn't fun trying to work with the original code (sorry), but I'm glad you've found it to be at least remotely useful...

        Show
        A B added a comment - Thanks for taking the time to improve the utility, Andrew. I know it wasn't fun trying to work with the original code (sorry), but I'm glad you've found it to be at least remotely useful...
        Hide
        Bryan Pendleton added a comment -

        Attached is skipBlankLines.diff.

        I was investigating using SQLToJUnit for conversion of groupBy.sql, but the master file groupBy.out contains some entirely blank lines, which was causing the command parser in SQLToJUnit to throw a NullPointerException.

        With this patch SQLToJUnit successfully processed all of groupBy.sql.

        Show
        Bryan Pendleton added a comment - Attached is skipBlankLines.diff. I was investigating using SQLToJUnit for conversion of groupBy.sql, but the master file groupBy.out contains some entirely blank lines, which was causing the command parser in SQLToJUnit to throw a NullPointerException. With this patch SQLToJUnit successfully processed all of groupBy.sql.
        Hide
        Bryan Pendleton added a comment -

        Committed skipBlankLines.diff to subversion as revision 573432.

        Show
        Bryan Pendleton added a comment - Committed skipBlankLines.diff to subversion as revision 573432.

          People

          • Assignee:
            Unassigned
            Reporter:
            A B
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development