CSE 331 Homework: Inventory
Due Friday, Aug 7 at 11:59pm.
In this homework you will build a simple terminal application to manage items in an inventory.
Starter code
Go to the CSE 331 public gitlab repository in the hwInventory folder. Click the blue "Code" button in the top right, and the click Download directory as zip at the very bottom of the popup. Extract the resulting file on your machine. You should see the following files:
Inventory.java: the specification for the inventory data structureInventoryImpl.java: starter file for your implementation of the inventory data structureInventorySpecTest.java: starter file for your specification-based testsInventoryImplTest.java: optional starter file for your implementation-based testsInventoryTerminalApp.java: starter file for your terminal applicationlib/: JUnit jar.Makefile: shortcuts for compiling and running (see below).
Software setup
You may use any Java development environment you want. If you have one you are already comfortable with, we recommend you use it.
Visual Studio Code
If you are looking for a Java development environment, we recommend Visual Studio Code because it is easy to set up. You will need the "Extension Pack for Java". (Open the extensions panel in VS Code and search for "Extension Pack for Java" and install it.)
Once you have VS Code and the extension pack installed, then:
- Use File -> Open Folder... and select the unzipped
hwInventoryfolder you downloaded earlier. - Open the
InventoryTerminalApp.javafile. - You should see a "Java activating" message near the bottom of your window.
- Once it is finished activating, you should see a green "Run" button above the
mainmethod inInventoryTerminalApp. Press the run button to run the starter code and confirm that your setup is working.
The rest of the starter code (in particular InventoryImpl.java) will
not compile due to unimplemented methods until you have finished Task 1 below.
Using the command line
Alternatively, you can run the code from the command line. From the unzipped
hwInventory directory,
make compile # compile everything
make run # run the terminal app
make test # run all tests
make clean # delete compiled .class files
The Makefile should work on macOS, Linux, and Windows (you'll need to install Make if you don't already have it). You can also copy paste the commands out of the Makefile to run them directly if you don't have Make.
These make targets will exit with error in the starter code due to unimplemented methods until you finish task 1 below.
Task 1: Implement and test the inventory
Read the specification of Inventory carefully. It describes an ADT
representing the state of an inventory.
Once you have read the required interface, then you should:
- Write your implementation in
InventoryImpl.java. - Write tests, split across two files as described below.
Specification-based vs implementation-based testing
A specification-based test relies only on behavior described in the specification. It would pass when run on any correct implementation of the spec, including yours, your classmate's, or the course staff's.
An implementation-based test additionally relies on choices a particular
implementation made. These are most often choices about behavior that the spec
leaves unspecified. For example, what happens when a method is invoked on an
input that violates a @requires? That behavior can only be tested in an
implementation-based way. These tests may be useful for your own development, but
they might not pass when run on a different but equally correct implementation.
For this reason, we have given you two different test files:
InventorySpecTest.javacontains only specification tests, that is, tests that only depend on behavior guaranteed by theInventoryspecification.InventoryImplTest.javacontains any additional tests you want to write that may depend on behavior unique to your implementation
We've given you one example test in InventorySpecTest.java. You'll need
to add many more to satisfy the coverage and bug-detection requirements below.
Only your specification tests in InventorySpecTest.java will be graded.
Specifically, we will grade your tests by:
- Run your spec tests against your implementation. They must all pass.
- Run your spec tests against the staff implementation, and possibly other correct implementations. They must all pass against those too. (If they don't pass when run against a different but still correct implementation, then that is an indication that the tests are testing behavior not required by the spec.)
- Run your spec tests against several deliberately buggy implementations we've prepared. Some points will be awarded based on how many of these buggy implementations your tests detect (i.e., cause to fail). A good test suite is able to distinguish correct implementations from incorrect ones. Tests that exercise a method but don't actually check meaningful behavior (e.g., calling a method without asserting anything about the returned value) won't catch many bugs.
So on the one hand, your spec tests must be thorough enough to catch buggy implementations. But on the other hand, your spec tests must not test any behavior that is not required by the specification. You should use what you learned about testing this quarter to assist you in forming your test suite.
The implementation test file will not be graded. You may leave it blank if you wish.
Task 2: The terminal application
Build a small interactive terminal application in
InventoryTerminalApp.java that lets the user manage an inventory from the command
line. Use the InventoryImpl data structure implementation you wrote in
Task 1.
The starter code for the terminal app includes a small "counter" demo to show you the basics of how to use a Scanner to make an interactive terminal application. You should delete this starter code and replace it with your real application.
You have the freedom to design the specifics of how the terminal application works, as long as your application supports all of the functionality described below. As long as a user can do each of the things in the scenarios below, you're free to design the interface however you like.
You do not need to submit JUnit tests for the terminal application. But you should run the application yourself and ensure that all required behavior works as desired. Course staff will grade your terminal application by running it and trying it themselves.
Required functionality
The application must let the user:
- ship: Process a shipment and increase inventory.
- buy: Process an order from your inventory.
- quantity: Show the current quantity of an item.
- history: Show an item's transaction history.
- item: Show the item's quantity and history.
- items: Show all items currently in the inventory.
- all: Show the quantity of all items.
- log: Show every transaction ever, in order.
- help: Display available commands and usage hints.
- exit: Close the app gracefully.
As a user-facing application, it should be mostly self-documenting: a user who has never run it before should be able to figure out what to do. At a minimum, the program should print a menu of available commands (or otherwise display the available options) so the user doesn't have to guess. It should also handle all inputs reasonably and with decent error messages. For example, if the user asks for an item that does not exist, then the program should not crash, but rather should print an error message and continue, allowing the user to retry.
Example Scenario
The following scenario illustrates the required functionality. Your application should be able to handle equivalent functionality, though you are free to use a different menu format and display information differently. Of course, just being able to handle this one example scenario correctly does not mean your code is correct in all cases.
Your 331 knowledge and your entrepreneurial spirit lead you to decide to start a new company WorstBuyâ„¢. You carry various items like keyboards, mice, and other forms of technology. The first thing you have to do is secure your stock of items, so what better to do with your computer science degree than write a program to help you do so? You receive a shipment of Apple products first, so you record them in your app, doing various checks manually to verify what you're storing.
======================================== Inventory Dashboard ======================================== Commands: ship <item> <qty> Record a shipment arriving (increases quantity) buy <item> <qty> Record a purchase (reduces quantity) quantity <item> Show current quantity of an item history <item> Show transaction history for an item item <item> Show quantity + history for an item items List all known item ids all Show current quantity of every item log Show every transaction ever, in order help Show this message exit Quit the app > ship MacbookPro 10000 Shipment recorded: +10000 MacbookPro (now 10000) > ship iPhone 2000 Shipment recorded: +2000 iPhone (now 2000) > quantity iPhone iPhone: 2000 > history iPhone 1. iPhone: shipment of +2000 > log 1. MacbookPro: shipment of +10000 2. iPhone: shipment of +2000 >
Now that you have some inventory that may make customers mistake you for an Apple store, you think it's time to open shop. Your first customer arrives and it's James! James, as PowerPoint's biggest hater, wants to buy a doc camera from you to use in his lectures. So he places the order to buy it from you but...
... > buy docCam 1 Error: no item called 'docCam' (try 'items') >
James, being deeply disappointed, asks "my disappointment is immeasurable and my day is ruined, what do you even have?" Using your really cool app you run the items command to find out just that.
... > items Items: iPhone, MacbookPro >
Since he already made the trip to your store, James decides to leave here with something. He decides to buy two Macbooks and one iPhone.
... > buy MacbookPro 2 Purchase recorded: -2 MacbookPro (now 9998) > buy iPhone 1 Purchase recorded: -1 iPhone (now 1999) >
Excited that you had your first sale you check over your inventory to make sure it's actually gone through!
... > log 1. MacbookPro: shipment of +10000 2. iPhone: shipment of +2000 3. MacbookPro: purchase of -2 4. iPhone: purchase of -1 > quantity iPhone iPhone: 1999 > history iPhone 1. iPhone: shipment of +2000 2. iPhone: purchase of -1 > item iPhone iPhone: 1999 1. iPhone: shipment of +2000 2. iPhone: purchase of -1 >
With your first sale done and the inventory checked, you decide to call it a day and close up shop.
... > exit Shutting Down...
Correctness and code quality
In addition to evaluating your tests (Task 1), we will grade your inventory ADT implementation and your terminal application on correctness and on code quality.
A passing test suite is good, but it does not guarantee that your code is correct. Despite this, you are responsible for turning in code that works, and for doing the work to convince yourself that it works. You should reason carefully about the spec, trace through your code and ensure it satisfies the spec in all cases.
Be sure your inventory ADT implementation follows all the rules for implementing an
ADT in 331. You must document in a comment the AF and RI, define and call
checkRep(), and defensively check fast preconditions.
The starter code already includes specifications for every method on the inventory
interface, so you don't need to write any new specs in
InventoryImpl.java. But your implementation must satisfy the specs
we've given you.
Submission
Submit the following files to the Homework Inventory assignment on Gradescope:
InventoryImpl.javaInventorySpecTest.javaInventoryImplTest.javaInventoryTerminalApp.java
You can either upload these files individually on Gradescope, or run
make submission to bundle them into a submission.zip and upload that.
You should not modify or submit Inventory.java.
We have set up a Gradescope autograder that will compile and run your code. It will run your tests on your own code and show you the results. It will also run one very basic staff test that makes sure you have implemented the zero-argument constructor for the Inventory ADT. Passing all the autograder tests does not guarantee your code is correct or high quality.