Question
Project Goals In this project, you will be developing a simple Java application (texttool) using an agile, test-driven process involving multiple deliverables. While you will
Project Goals
In this project, you will be developing a simple Java application (texttool) using an agile, test-driven process involving multiple deliverables. While you will receive one grade for the entire project, each deliverable must be completed by its own due date, and all deliverables will contribute to the overall project grade.
Specification of thetexttool Utility
texttoolis a simple command-line utility written in Java with the following specification:
Summary
texttool allows for simple text manipulation of the content of a file.
Syntax
texttool [OPTIONS] FILE
Description
Program texttool performs basic text transformations on lines of text from an input FILE. Unless the -f option (see below) is specified, the program writes transformed text to stdout and errors/usage messages to stderr. The FILE parameter is required and must be the last parameter. OPTIONS may be zero or more of the following and may occur in any order:
- -f Edit file in place. The program overwrites the input file with transformed text instead of writing to stdout. This option must be mutually exclusive with -o below. Input file is assured to always be writable.
- -o The program writes the output tooutput_file_name with transformed text instead of writing to stdout. This option must be mutually exclusive with -f above. Ifoutput_file_name already exists, the program shall result in an error.
- -r Replaces the first instance of stringoldin each line with stringnew. The search is case-sensitive. This option must be mutually exclusive with -c below.
- -i Used with the -r flag ONLY; the search of -r becomes case-insensitive.
- -p Adds the stringprefix at the beginning of each line.
- -d Duplicate each line in the file n times, where n is an integer in the inclusive range of 1 to 10. The duplicate lines shall be sequential to each other.
- -c Encodes the text using acipher that replaces each alphabetic characterchar with a new character that is atnpositions fromchar in the English alphabet (wrapping from "z" to "a" or from "a" to "z" if needed). Here, n is an integer in the inclusive range of -25 to 25, thus negative values n are valid. The cipher shall respect capitalization and ignore special characters and numbers. This option must be mutually exclusive with -r above.
NOTES:
- While the last command-line parameter provided is always treated as the filename, OPTIONS flags can be provided in any order and shall be applied as follows:
- Options -f/-o/-i shall be processed first, as they determine global parameters of the computation.
- Options -r, -p, -c, and -d shall be processed in this order. That is: (1) if -r is present, then replacements are performed based on the option parameters, using a case insensitive old string if -i is present; (2) if -p is present, then a prefix shall be applied; (3) if -c is present, apply the given cipher; (4) if -d is present, then duplicate the lines based upon the specified parameter.
- To keep this application simple, all errors shall result in display of the standard usage message.
- Specifying option -i without having specified option -r shall result in an error.
- Specifying option -r with an empty string as the parameter shall result in an error.
- Specifying option -p with an empty string as the parameter shall result in an error.
- Specifying option -d with a non-integer value or an integer out of range shall result in an error.
- Specifying option -c and -r simultaneously shall result in an error.
- Specifying option -c without a valid integer value or an integer out of range shall result in an error.
- If options are repeated, only their last occurrence is applied.
- All program option parameters are required, resulting in an error if omitted.
- You shall assume that the command line parameter strings will not contain newline characters ( , , and so on), as the behavior of the program would be platform dependent and may result in errors during grading. Therefore,there should be no test cases using these values as option parameters.
- An empty input file shall produce an empty output file.
- The last line of a non-empty input file must be newline terminated. Otherwise, the program shall generate an error.
EXAMPLES OF USAGE(In the following, "" represents a newline character.)
Example 1: texttool -f FILE
input FILE:
alphanumeric123foobar
edited FILE:
alphanumeric123foobar
stdout:nothing sent to stdout
stderr:nothing sent to stderr
Example 2: texttool -r 123 456 FILE
input FILE:
alphanumeric123foobar123
edited FILE:file not edited
stdout:
alphanumeric456foobar123
stderr:nothing sent to stderr
Example 3: texttool -i -r foo candy FILE
input FILE:
alphanumeric123FOObar123
edited FILE:file not edited
stdout:
alphanumeric123candybar123
stderr:nothing sent to stderr
Example 4: texttool -p ## FILE
input FILE:
alphanumeric123foobar
edited FILE:file not edited
stdout:
##alphanumeric123foobar
stderr:nothing sent to stderr
Example 5: texttool -d 3 FILE
input FILE:
alphanumeric123foobar
edited FILE:file not edited
stdout: alphanumeric123foobar
alphanumeric123foobar
alphanumeric123foobar
alphanumeric123foobar
stderr:nothing sent to stderr
Example 6: texttool -r foo FOO -f -p !!! -d 1 FILE
input FILE:
foobar0Foobar1
foobar2foobar3
foobar4Foobar5
foobar6foobar7
foobar8Foobar9
edited FILE:
!!!FOObar0Foobar1
!!!FOObar0Foobar1
!!!FOObar2foobar3
!!!FOObar2foobar3
!!!FOObar4Foobar5
!!!FOObar4Foobar5
!!!FOObar6foobar7
!!!FOObar6foobar7
!!!FOObar8Foobar9
!!!FOObar8Foobar9
stdout:nothing sent to stdout
stderr:nothing sent to stderr
Example 7: texttool -c -20 -d 5 -d 1 -p !!! -p ## FILE
input FILE:
alphanumeric123foobar
edited FILE:file not edited
stdout: ##grvngtaskxoi123luuhgx
##grvngtaskxoi123luuhgx
stderr:nothing sent to stderr
Example 8: texttool
input FILE:
01234abc
56789def
01234ABC
56789DEF
edited FILE:file not edited
stdout:nothing sent to stdout
stderr:
Usage: texttool [ -f | -o output_file_name | -i | -r old new | -p prefix | -c n | -d n ] FILE
Example 9: texttool -c 1 FILE
input FILE:
alphanumeric123foobar
edited FILE:file not edited
stdout:
bmqibovnfsjd123gppcbs
stderr:nothing sent to stderr
Deliverables Summary
This part of the document is provided to help you keep track of where you are in the individual project and will be updated in future deliverables.
DELIVERABLE 1
- Provided:
- texttool specification
- Skeleton of the main class fortexttool
- Example tests and skeleton of the test class to submit
- JUnit libraries
- Expected:
- Part I (Category Partition)
- catpart.txt: TSL file you created
- catpart.txt.tsl: test specifications generated by theTSLgenerator tool when run on your TSL file.
- Part II (Junit Tests)
- Part I (Category Partition)
Junit tests derived from your category partition test frames (MyMainTest.java)
DELIVERABLE 2 (this deliverable, see below for details)
- Provided:
- Reference implementation oftexttool utility
- Expected:
- Possibly revised set of tests that (1) pass on the reference implementation, (2) cover a set of scenarios (provided through Gradescope), and (3) have suitable oracles.
Deliverable 1: Instructions
Part I
Generatebetween 50 and 90 test-case specifications (i.e., generated test frames) for thetexttool utility using the category-partition method presented in lesson P4L2.Make sure to watch the lesson and demo before getting started.
When defining your test specifications, your goal is to suitably cover the domain of the application under test, includingrelevant erroneous inputs and input combinations. Just to give you an example, if you were testing a calculator, you may want to cover the case of a division by zero.
Do not manually generate combinations of inputs as single choices. Instead, use multiple categories and choices with necessary constraints to cause the tool to generate meaningful combinations. Using the calculator example again, you should not offer choices "add", "multiply", and also "add and multiply" in a single category.
In particular,make sure to use constraints (error and single), selector expression (if), and properties appropriately, rather than eliminating choices, to keep the number of test cases within the specified thresholds.
Note thatthe domain is that of the java application under test, so you can assume that anything the shell would reject (e.g., unmatched double quotes) will not reach the application. In other words,you must test for invalid input arguments, but do not need to test for errors involving parsing the command-line arguments before they are sent to the java application. In other words, you may assume thatMain.main() will be called with a validString[] of args. Although this application will only use the simplified command-line parsing given in the specification above, you can find more details about comprehensive command-line argument parsing atthis link. To illustrate, the sample tests in Part II will demonstrate how input arguments would be sent to your application.
Please also keep in mind thatyou are only required to specify test inputs, but you do not have to specify the expected outcome for such inputs in Part I. It is therefore OK if you do not know how the system would behave for a specific input. Using the calculator example, you could test the case of a division by zero even if you did not know how exactly the calculator would behave for that input.
Tools and Useful Files
You will use theTSLgenerator tool to generate test frames starting from a TSL file, just like we did in the demo for lesson P4L2. Versions of theTSLgenerator for Linux, Mac OS X, and Windows, together with a user manual, are available at:
- TSLgenerator-manual.txt
- TSL generator for Linux
- TSL generator for Mac OS
- TSL generator for Windows 8 and newer
- TSL generator for Windows XP and earlier
We are also providing the TSL file for the example we used in the lesson,cp-example.txt, for your reference.
Important:
- These are command-line tools, which means thatyou have to run them from the command line, as we do in the video demo, rather than by clicking on them.
- On Linux and Mac systems, you may need to change the permissions of the files to make them executable using thechmod utility. To run the tool on a Mac, for instance, you should do the following, from a terminal: chmod +x TSLgenerator-mac ./TSLgenerator-mac
- You can run theTSLgenerator as follows: [--manpage] [-cs] infile [-o outfile] Where is the specific tool for your architecture, and the command-line flags have the following meaning:
--manpage | Prints the man page for the tool. |
-c | Reports the number of test frames that would be generated, without actually producing them. |
-s | Outputs the result to standard output. |
-o outfile | Outputs the result to file outfile,unless the -s option is also used. |
- If you encounter issues while using the tool, please post a public question on Ed Discussion and consider running the tool on the VM provided for the class or on a different platform (if you have the option to do so). Gradescope will execute the tool on a Linux platform.
Deliverable 2: Instructions
In this deliverable, we will assume that someone else in your company implemented thetexttool utility while you were creating test cases for it. For the sake of the assignment, we will also assume that your colleague is an infallible developer and produced a flawless implementation. Consequently,all the test cases you created for Deliverable 1 are supposed to pass on this implementation.
To complete this deliverable, you will thus submit your test cases (i.e., classMyMainTest) and make sure that they pass on the reference implementation (Gradescope will run them for you and report information about passing and failing tests).
main.java
public class Main { // Empty Main class for compiling Individual Project. // During Deliverable 1 and Deliverable 2, DO NOT ALTER THIS CLASS or implement it public static void main(String[] args) { // Empty Skeleton Method } private static void usage() { System.err.println("Usage: texttool [ -f | -o output_file_name | -i | -r old new | -p prefix | -c n | -d n ] FILE"); } }
mainTest.java
public class MainTest { @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); private final Charset charset = StandardCharsets.UTF_8; private ByteArrayOutputStream outStream; private ByteArrayOutputStream errStream; private PrintStream outOrig; private PrintStream errOrig; @Before public void setUp() throws Exception { outStream = new ByteArrayOutputStream(); PrintStream out = new PrintStream(outStream); errStream = new ByteArrayOutputStream(); PrintStream err = new PrintStream(errStream); outOrig = System.out; errOrig = System.err; System.setOut(out); System.setErr(err); } @After public void tearDown() throws Exception { System.setOut(outOrig); System.setErr(errOrig); } /* * TEST UTILITIES */ // Create File Utility private File createTmpFile() throws Exception { File tmpfile = temporaryFolder.newFile(); tmpfile.deleteOnExit(); return tmpfile; } // Write File Utility private File createInputFile(String input) throws Exception { File file = createTmpFile(); OutputStreamWriter fileWriter = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8); fileWriter.write(input); fileWriter.close(); return file; } private String getFileContent(String filename) { String content = null; try { content = Files.readString(Paths.get(filename), charset); } catch (IOException e) { e.printStackTrace(); } return content; } /* * TEST CASES */ /* texttool -f FILE input FILE: alphanumeric123foobar edited FILE: alphanumeric123foobar stdout: nothing sent to stdout stderr: nothing sent to stderr */ @Test public void exampleTest1() throws Exception { String input = "alphanumeric123foobar!" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-f", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertTrue("stdout output should be empty", outStream.toString().isEmpty()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -r 123 456 FILE input FILE: alphanumeric123foobar123 edited FILE: file not edited stdout: alphanumeric456foobar123 stderr: nothing sent to stderr */ @Test public void exampleTest2() throws Exception { String input = "alphanumeric123foobar123" + System.lineSeparator(); String expected = "alphanumeric456foobar123" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-r", "123", "456", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -i -r foo candy FILE input FILE: alphanumeric123FOObar123 edited FILE: file not edited stdout: alphanumeric123candybar123 stderr: nothing sent to stderr */ @Test public void exampleTest3() throws Exception { String input = "alphanumeric123FOObar123" + System.lineSeparator(); String expected = "alphanumeric123candybar123" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-i", "-r", "foo", "candy", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -p ## FILE input FILE: alphanumeric123foobar edited FILE: file not edited stdout: ##alphanumeric123foobar stderr: nothing sent to stderr */ @Test public void exampleTest4() throws Exception { String input = "alphanumeric123foobar" + System.lineSeparator(); String expected = "##alphanumeric123foobar" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-p", "##", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -d 3 FILE input FILE: alphanumeric123foobar edited FILE: file not edited stdout: alphanumeric123foobar alphanumeric123foobar alphanumeric123foobar alphanumeric123foobar stderr: nothing sent to stderr */ @Test public void exampleTest5() throws Exception { String input = "alphanumeric123foobar" + System.lineSeparator(); String expected = "alphanumeric123foobar" + System.lineSeparator() + "alphanumeric123foobar" + System.lineSeparator() + "alphanumeric123foobar" + System.lineSeparator() + "alphanumeric123foobar" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-d", "3", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -r foo FOO -f -p !!! -d 1 FILE input FILE: foobar0Foobar1 foobar2foobar3 foobar4Foobar5 foobar6foobar7 foobar8Foobar9 edited FILE: !!!FOObar0Foobar1 !!!FOObar0Foobar1 !!!FOObar2foobar3 !!!FOObar2foobar3 !!!FOObar4Foobar5 !!!FOObar4Foobar5 !!!FOObar6foobar7 !!!FOObar6foobar7 !!!FOObar8Foobar9 !!!FOObar8Foobar9 stdout: nothing sent to stdout stderr: nothing sent to stderr */ @Test public void exampleTest6() throws Exception { String input = "foobar0Foobar1" + System.lineSeparator() + "foobar2foobar3" + System.lineSeparator() + "foobar4Foobar5" + System.lineSeparator() + "foobar6foobar7" + System.lineSeparator() + "foobar8Foobar9" + System.lineSeparator(); String expected = "!!!FOObar0Foobar1" + System.lineSeparator() + "!!!FOObar0Foobar1" + System.lineSeparator() + "!!!FOObar2foobar3" + System.lineSeparator() + "!!!FOObar2foobar3" + System.lineSeparator() + "!!!FOObar4Foobar5" + System.lineSeparator() + "!!!FOObar4Foobar5" + System.lineSeparator() + "!!!FOObar6foobar7" + System.lineSeparator() + "!!!FOObar6foobar7" + System.lineSeparator() + "!!!FOObar8Foobar9" + System.lineSeparator() + "!!!FOObar8Foobar9" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-r", "foo", "FOO", "-f", "-p", "!!!", "-d", "1", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertTrue("stdout output should be empty", outStream.toString().isEmpty()); assertEquals("input file content not matched", expected, getFileContent(inputFile.getPath())); } /* texttool -c -20 -d 5 -d 1 -p !!! -p ## FILE input FILE: alphanumeric123foobar edited FILE: file not edited stdout: ##grvngtaskxoi123luuhgx ##grvngtaskxoi123luuhgx stderr: nothing sent to stderr */ @Test public void exampleTest7() throws Exception { String input = "alphanumeric123foobar" + System.lineSeparator(); String expected = "##grvngtaskxoi123luuhgx" + System.lineSeparator() + "##grvngtaskxoi123luuhgx" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-c", "-20", "-d", "5", "-d", "1", "-p", "!!!", "-p", "##", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool input FILE: 01234abc 56789def 01234ABC 56789DEF edited FILE: file not edited stdout: nothing sent to stdout stderr: Usage: texttool [ -f | -o output_file_name | -i | -r old new | -p prefix | -c n | -d n ] FILE */ @Test public void exampleTest8() throws Exception { String input = "01234abc" + System.lineSeparator() + "56789def" + System.lineSeparator() + "01234ABC" + System.lineSeparator() + "56789DEF" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {}; Main.main(args); assertEquals("stderr output does not match", "Usage: texttool [ -f | -o output_file_name | -i | -r old new | -p prefix | -c n | -d n ] FILE", errStream.toString().strip()); assertTrue("stdout output should be empty", outStream.toString().isEmpty()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } /* texttool -c 1 FILE input FILE: alphanumeric123foobar edited FILE: file not edited stdout: bmqibovnfsjd123gppcbs stderr: nothing sent to stderr */ @Test public void exampleTest9() throws Exception { String input = "alphanumeric123foobar" + System.lineSeparator(); String expected = "bmqibovnfsjd123gppcbs" + System.lineSeparator(); File inputFile = createInputFile(input); String[] args = {"-c", "1", inputFile.getPath()}; Main.main(args); assertTrue("stderr output should be empty", errStream.toString().isEmpty()); assertEquals("stdout output does not match", expected, outStream.toString()); assertEquals("input file content not matched", input, getFileContent(inputFile.getPath())); } }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started