/** Test Exprs. * See http://www.radford.edu/itec380/2024fall/Homeworks/Project/ * * This file includes both some specific tests for OG0 and OG1, * as well as some helper-functions which are helpful for OG0-OG3. * HOWEVER, they aren't a cure-all -- * no tests are made against the expected internal representation (Expr-tree). * For example, testParseToString just checks that parse and * 'toString' are inverses of each other; if they are both * the identity function, it would pass all tests. * * Compiling this function may generate a warning * ('unchecked generic array creation', due to using Arrays.asList * and varargs). * * For compiling with junit (if your IDE doesn't automatically recognize it), * see the note at end of this file. * * @author Ian Barland * @version 2024.Nov.11 */ import java.util.*; public class ExprTest /* extends junit.framework.TestCase */ { /** Manually call our test-functions * (in case calling JUnit from your IDE isn't easy). */ public static void main(String... args) { ExprTest t = new ExprTest(); t.setUp(); t.testMyStuff(); t.tearDown(); t.setUp(); t.testTowardsAutomating(); t.tearDown(); t.setUp(); t.testParseToString(); t.tearDown(); t.setUp(); t.testEval(); t.tearDown(); // Alternately, this might work, but might require declaring a package // rather than the un-named package: calling `main` from org.junit: // org.junit.runner.JUnitCore.main("ExprTest"); t.dbg("Testing complete.\n"); } static final double TOLERANCE = 0.000001; String e0 = "34"; String e1 = "bruh 34 slaps"; String e2 = "finna rizz 4 3"; String e3 = "bruh bruh finna rizz 4 bruh 3 slaps slaps slaps"; String e4 = "finna rizz bruh 43 slaps finna glow up 2 3"; java.util.List> allTests; /* allTests should be a list of pairs: * a OG0 Expr, and what that expression evaluates to. * Use a Double, for Num values. */ // @Test // Some expressions to test in a non-automated way: public void testMyStuff() { dbg("testMyStuff: parsing\n"); assertEquals( Expr.parse("99"), new Num(99)); assertEquals( Expr.parse("-99"), new Num(-99)); assertEquals( Expr.parse("bruh 34 slaps"), new Paren( new Num(34) )); assertEquals( Expr.parse(" bruh 34 slaps "), new Paren( new Num(34) )); assertEquals( Expr.parse("finna rizz 3 4"), new BinOp("rizz", new Num(3), new Num(4)) ); assertEquals( Expr.parse("finna rizz bruh 99 slaps finna glow up 3 4"), new BinOp( "rizz", new Paren(new Num(99)), new BinOp( "glow up", new Num(3), new Num(4))) ); assertEquals( Expr.parse("no cap? 7 ong 9 bet 3"), new IfZero( new Num(7), new Num(9), new Num(3))); assertEquals( Expr.parse("no cap? finna glow up 3 4 ong 7 bet bruh 99 slaps"), new IfZero(new BinOp("glow up", new Num(3), new Num(4)), new Num(7), new Paren(new Num(99)))); assertEquals( Expr.parse(""" no cap? no cap? 3 ong 7 bet 9 ong bruh 99 slaps bet finna rizz bruh 34 slaps finna glow up 3 4"""), new IfZero(new IfZero(new Num(3), new Num(7), new Num(9)), new Paren(new Num(99)), new BinOp( "rizz", new Paren(new Num(34)), new BinOp( "glow up", new Num(3), new Num(4)))) ); // toString dbg("testMyStuff: testing toString\n"); assertEquals( Expr.parse("34").toString(), "34"); assertEquals( Expr.parse("bruh 34 slaps").toString(), "bruh 34 slaps"); assertEquals( Expr.parse(" bruh 34 slaps ").toString(), "bruh 34 slaps"); assertEquals( Expr.parse("finna rizz 3 4 ").toString(), "finna rizz 3 4"); assertEquals( Expr.parse("finna rizz bruh 34 slaps finna glow up 3 4").toString(), "finna rizz bruh 34 slaps finna glow up 3 4"); assertEquals( Expr.parse("no cap? 7 ong 9 bet 3").toString(), "no cap? 7 ong 9 bet 3"); assertEquals( Expr.parse("no cap? finna glow up 3 4 ong 7 bet bruh 34 slaps").toString(), "no cap? finna glow up 3 4 ong 7 bet bruh 34 slaps"); assertEquals( Expr.parse(""" no cap? finna rizz bruh 34 slaps finna glow up 3 4 ong no cap? 7 ong 9 bet no cap? 4 ong 5 bet 6 bet bruh 34 slaps""").toString(), "no cap? finna rizz bruh 34 slaps finna glow up 3 4 ong no cap? 7 ong 9 bet no cap? 4 ong 5 bet 6 bet bruh 34 slaps"); //eval dbg("testMyStuff: testing eval\n"); assertEquals( new Num(99).eval(), new Num(99) ); assertEquals( Expr.parse("99").eval(), new Num(99) ); assertEquals( Expr.parse("bruh 99 slaps").eval(), new Num(99) ); assertEquals( Expr.parse("finna rizz 3 4").eval(), new Num(7) ); assertEquals( Expr.parse("finna rizz bruh 99 slaps finna glow up 3 4").eval(), new Num(111) ); assertEquals( Expr.parse("no cap? 7 ong 9 bet 3").eval(), new Num(3) ); assertEquals( Expr.parse("no cap? finna glow up 3 4 ong 7 bet bruh 99 slaps").eval(), new Num(99) ); assertEquals( Expr.parse(""" no cap? no cap? 3 ong 7 bet 9 ong bruh 99 slaps bet finna rizz bruh 34 slaps finna glow up 3 4""").eval(), new Num(46) ); // "if no cap? 3 ong 7 bet 9 // equinox bruh 99 slaps // : finna rizz // bruh 34 slaps // finna glow up 3 4" // Add more specific tests here, // if you want things more specific that provided via adding to `allTests` below. } // @Test public void testTowardsAutomating() { dbg("testTowardsAutomating\n"); // we can automate checking that parse! is the (right)inverses of expr->string: for( String e : Arrays.asList(e0,e1,e2,e3,e4) ) { assertEquals( Expr.parse(e).toString(), e ); } // Though we also want to check that e0..e4 eval to 34,34,7,7,49 respectively. Iterator exps = Arrays.asList(e0,e1,e2,e3,e4).iterator(); Iterator dubs = Arrays.asList(34.0, 34.0, 7.0, 7.0, 49.0).iterator(); while (exps.hasNext()) { Num actual = (Num)(Expr.parse(exps.next()).eval()); Num expected = new Num(dubs.next()); assertEquals( actual, expected ); } // The above is a promising start, to automating tests. // Okay, we'll generalize the above to a more complete test-harness. // One thing, is that we don't want to have two parallel-lists; // instead keep a list of pairs. // Three sorts of tests we want to make, for many different exprs: assertEquals( Expr.parse("finna rizz 4 3"), new BinOp("rizz", new Num(4), new Num(3)) ); assertEquals( Expr.parse("finna rizz 4 3").eval(), new Num(7) ); assertEquals( Expr.parse("finna rizz 4 3").toString(), "finna rizz 4 3"); } /** * Sets up the test fixture. * Called before every test case method. */ // @Test public void setUp() { /* allTests should be a list of pairs: * a OG0 Expr, and what that expression evaluates to. * Use a Double, for Num values. */ allTests = java.util.Arrays.asList( //;>>>OG0-tests" new Pair("7", 7) ,new Pair("bruh 3 slaps", 3) ,new Pair("finna rizz 3 4", 7) ,new Pair("finna glow up 3 4", 12) ,new Pair("finna rizz finna rizz 3 4 finna glow up 3 4", 19) ,new Pair("finna glow up bruh 3 slaps bruh finna rizz 2 3 slaps", 15) ,new Pair("no cap? 0 ong 1 bet 2", 1) ,new Pair("no cap? 1 ong 1 bet 2", 2) ,new Pair("no cap? finna rizz 3 -3 ong 1 bet 2", 1) ,new Pair("no cap? finna rizz no cap? no cap? 0 ong 1 bet 2 ong 3 bet 4 -3 ong 1 bet 2", 2) /********* //;>>>OG1-tests //; Uncomment these tests, once `mod` is implemented: ,new Pair("finna cancel 3 4", 3) ,new Pair("finna cancel finna rizz 5 6 3", 2) ,new Pair("finna cancel 8.1 3", 2.1) ,new Pair("finna cancel 8 3.1", 1.8) ,new Pair("finna cancel -8.1 3", 0.9) ,new Pair("finna cancel -8 3.1", 1.3) ,new Pair("finna cancel 8.1 -3", -0.9) ,new Pair("finna cancel 8 -3.1", -1.3) ,new Pair("finna cancel -8.1 -3", -2.1) ,new Pair("finna cancel -8 -3.1", -1.8) ,new Pair("finna cancel 8 2", 0) ,new Pair("finna cancel -8 2", 0) ,new Pair("finna cancel 8 -2", 0) ,new Pair("finna cancel -8 -2", 0) ,new Pair("finna cancel 8 3", 2) ,new Pair("finna cancel -8 3", 1) ,new Pair("finna cancel 8 -3", -1) ,new Pair("finna cancel -8 -3", -2) // STUDENT-TODO: YOU-MUST-CREATE-SOME-TESTS-FOR-IfGE's *********/ ); } ////////////////////////////////////////////////////////////////////////////////////////////// ///////////// DO NOT CHANGE the below ///////////// (unless you really want to) ///////////// ////////////////////////////////////// helper functions //;////////////////////////////////// /** For every element in allTests, * parse the string, and then call toString on the result, * checking that we get back exactly the input string * (up to whitespace). */ // @Test public void testParseToString() { dbg("testParseToString\n"); for ( Pair t : allTests ) { String expected = t.first(); String actual = Expr.parse( t.first() ).toString(); if (! UtilIan.equalsIgnoreWhitespace(expected, actual, Expr.PUNCTUATION)) { // This assert will fail; just present it to the user: assertEquals( expected, actual ); } else { logPassedTest(); } } dbg("\n"); } /** For every element in allTests, * parse the string and eval the result, * checking that we get back the second item in the pair. * If the second item is a Java Number, convert it to an OG0 Num, * and leave the double-comparison to Num.equals(Object). */ // @Test public void testEval() { dbg("testEval\n"); for ( Pair t : allTests ) { assertEquals( Number.class.isInstance(t.second()) ? new Num( ((Number)t.second()).doubleValue() ) : t.second(), Expr.parse( t.first() ).eval() ); logPassedTest(); } dbg("\n"); } private int testCaseNum = 0; public void logPassedTest() { ++testCaseNum; System.err.printf(".%s", (testCaseNum % 5 == 0) ? " " : "" ); } /** * Tears down the test fixture. * Called after every test case method. */ public void tearDown() { } // If you want to use real JUnit, then comment-out this homebrewed `assertEquals`. // (Also, yuou can UNcomment our `@Test` annotations for the functions below.) // /** assert that `actual.equals(expected)`. * Comment out if actually using JUnit. */ static void assertEquals( Object actual, Object expected ) { if (! actual.equals(expected)) throw new AssertionError(String.format("assertEquals Failed: %s ≠ %s.", actual, expected)); } /** Just like `System.err.printf` but for debugging-output; * comment out its body to disable. * (This same method might be repeated in multiple classes, so that * you turn messages on/off on a per-file basis.) * @see java.io.PrintStream#printf * @param fmt the format string * @param infos Any data needed by the `fmt` (one item per '%' in `fmt`) */ public void dbg( String fmt, Object... infos ) { System.err.printf( fmt, infos ); testCaseNum = 0; // reset the grouping of "."s for passing test-cases. } } /* In the OG0-java code, a couple of classes extend junit.framework.TestCase. In order to compile these, you'll need to have that class (and others) in your CLASSPATH. I know that BlueJ comes with the junit-classes automatically, and I imagine that Eclipse does, as well. If you're getting an error "package junit.framework does not exist", you'll want to download 'junit.jar' (I got it from junit.org), and extract it somewhere in your classpath (e.g., in the same dir as your project). To run the tests [again, BlueJ and Eclipse have buttons to do this] from the command line, you'd type: java org.junit.runner.JUnitCore TestExpr Some slight further info at http://www.radford.edu/itec380/2024fall-ibarland/Homework/Project/OG0-java/how-to-run-junit.html */