470 likes | 607 Views
What is Unit Testing?. Unit Testing (Definition). Writing snippets of code that try to use methods (functions) from your program.
E N D
Unit Testing (Definition) • Writing snippets of code that try to use methods (functions) from your program. • Each snippet should test one (and only one) function......by calling the function, then comparing what the function actually produced to what it was supposed to produce. • Running the test code thus verifies that (at least part of) your program is doing what it’s supposed to.
Example Function To Test • public bool isPrime( int num){ /*implementation omitted*/} • Definition of a prime number: • “A prime number (or a prime) is a natural number which has exactly two distinct natural number divisors: 1 and itself.” (Wikipedia) • “The number 1 is by definition not a prime number”
Example Test Cases • public bool isPrime( int num){ /*implementation omitted*/} • Test with: • small primes (2, 3, 5, 7, 11) • large primes • non-primes (1, 4, 9, 12, 11*17) • zero • negative numbers
What is NUnit? • A free, open-source framework to help people create their own unit tests for any .Net language • We’ll use it for C# • Related to (“inspired by”) JUnit • JUnit is for Java testing
NUnit’s Goal(s): • Make it quick and easyto create unit tests, and to run those tests,and to get a list of which tests passed/failed.
How do I Use NUnit? • For this class, you will NOT be required to create your own Unit Tests. • You ARE required to write software that passes tests. The tests are provided to you, by the teacher
How do I Use NUnit? • You will download a starter project, which includes all the NUnit materials • Extract the .ZIP
Open the Solution (.SLN) file Note multiple projects There are three projects inside the starter solution: 01_PCE_Test_Runner This contains all the (instructor-provided) code that handles running the tests. This includes running the test in the GUI, and running the auto-grading logic 02_PCE_ForTests This is where the units tests themselves are located 03_PCE_StudentCode This is where YOUR CODE must be put Details: Solution Setup 10
01_PCE_Test_Runner • Ignore anything except the RunTests.cs • You can set the ‘mode’ here (you’ll see this later)
02_PCE_ForTests • This project contains all the tests • TestHelpers.cs contains stuff that multiple tests, across multiple assignments, make use of • Input/output capturing code • ‘Fuzzy’ comparisons
02_PCE_ForTests • PCE_Tests_To_Run.cs contains the actual tests – you’ll want to look in here for the details of each particular test.
03_PCE_Student_Code • This is where YOUR CODE will be put. • There will be just one file (Student_Answers.cs) • Your code (that you will hand in) always goes into Student_Answers.cs
03_PCE_Student_Code • If you want to experiment with a normal, console application, you do so by setting this project as the startup project, and then adding code to Main.
Details: GUI Test Runner • Make sure that “01_PCE_Test_Runner” is startup project • Right-click on it, and “Set as startup project” if it’s not • Make sure that in RunTests.cs, the linedoThis = RUN_TEST_IN_GUI; is uncommented • In VS: DebugStart (Without) Debugging • (If either doesn’t work, email prof!) • In the NUnit test runner: click ‘Run’ button • Be careful about which test(s) you’ve selected
Details: GUI Test Runner • NUnit should auto-reload your code when you recompile • If it doesn’t, you can force it to reload: File Reload Project orFile Reload Tests • You can then leave the test runner open, switch back to Visual Studio,change your program, and re-run your tests • Without having to quit-and-restart NUnit
How to find a failing test • Run the test(s) in the GUI • Get the name of a test that is failing • Edit Find And Replace Find In Files • Type in the name of the failing test & go find it. • In 02_PCE_ForTests, in PCE_Tests_To_Run.csfind the test by hand
Details: GUI Test Runner • Note the tabs at the bottom: • Errors And Failures: • Lists out the exact error message when the test failed • Tries to tell you where the failure occurred • Tests Not Run: • This should never happen (unless there’s an error with the test) • Test Output: • Anything you (or the test) Console.Writes will be displayed here
[Test] Attribute • [Test] • Specifies that test will be automatically called by NUnit. • The GUI automatically finds this test, and gets the name to display in the GUI
Attributes to ignore: • [Category] • Used by the instructor to put a test into a grading category • [TestFixture], [TimeOut], [Description] • Used to tell Nunit about tests
Execution of a test • NUnit ‘magically’ finds the tests to run • Once the test starts, it runs just like normal code • We can tell NUnit to check that certain things are true at certain points, and fail if they’re not true • This is done using the Assert.That command • If the function crashes (or throws exception), then the crash will be caught, prevented (normally), and the test will fail
Basic (Failing) Test • Assert.That( false, “msg” ); • What this does: • If the first parameter (‘false’) is false,then the test will fail, with the message “msg” • Test: Basic_Fail in the Nunit_Demo project
More typical pattern boolcorrectAnswer = false; Assert.That(correctAnswer, “msg” ); • This separates out the ‘is it correct?’ logic from the Assert statement • Notice that we can (and often will) use this pattern • Test: Basic_Fail_2, Basic_Fail_3
Using Assert Like Console.Write* • “Message” can work like Console.WriteLine: • int num = 10; • Assert.That( num == 12, “num={0} isn’t what we expected”, num); • Test: Basic_Console_WriteLine
Calling Student Code • Typically, a test will call into your code, check the result, and then Assert that your answer is the same as the expected answer • Because the test code is in another project, you MUST make your classes PUBLIC in the StudentCode project • This will either have been done for you, or else we’ll cover how to create your own classes in C#
Calling Student Code • This is the first ‘real’ unit test Call into your code Check the answer Pass (or fail) the test • Test: Basic_Unit_Test
Debugging Strategy: Printing • If you’re having trouble getting a test to pass, you can try adding print statements to your code, so that as the program runs, it tells you about what it’s doing
Redirecting I/O • Certain tests may redirect input, output • This means that they can ‘feed’ input to your code, and ‘capture’ the output that you produce • Capturing Console.Out in the Test • Importance of the ‘fuzzy’ string comparison • Test-Supplied Console.In
Output (captured by the test) • Using the TestHelpers software, the tests can capture output. • This is in the TestHelpers.cs file ; you’re welcome to look at it, if you’re curious about how it works • Anything that you print (using Console.Write) can be captured • Test: Unit_Test_Console_WriteLine
Fuzzy String Comparisons • The TestHelpers software also provides for a number of helpful routines, including ‘fuzzy’ comparisons • ‘Fuzzy’ for strings means case-insensitive, and without (too much) regard for blank spaces • Test: Unit_Test_Console_WriteLine_Fuzzy
Test-Supplied Input • The test can also assemble a string, which will be used as the input to your code. • Whenever you call Console.Readline, you will read everything up to the next newline • Enter key (Newline) in C#: \n • Example of input: • “2\n3\nquit\n” is the same as typing 2<enter>3<enter>quit<enter> • Test: Unit_Test_Console_IO_Fuzzy
[Values] Attribute • public void Unit_Test_Values( [Values(-1, 0, 1, 10)]intvalueToTry) • Tells NUnit to call this function four separate times: • once with valueToTry set to -1 • once with valueToTry set to 0, • once with valueToTry set to 1 • once with valueToTry set to 10 • Test: Unit_Test_Values
[Values] Attribute - Combo • public void Unit_Test_Values_2([Values(1, 10)]int a, [Values(2, 4)]int b) • Tells NUnit to call this function with ALL POSSIBLE COMBINATIONS OF a and b: • a = 1, b = 2 • a = 1, b = 4 • a = 10, b = 2 • a = 10, b = 4 • Test: Unit_Test_Values_2
[TestCase] Attribute [TestCase( 1, 2)] [TestCase( 10, 4)] public void Unit_Test_TestCase(int a, int b) • Tells NUnit to call this function with EACH TestCase: • a = 1, b = 2 • a = 10, b = 4 • Test: Unit_Test_TestCase
Tests that use the [Setup] Attribute • Notice that before each test, the method marked with [Setup] will be run • In the example test, we’ll use this to initialize x to be 10, y to be 20, and ex5 to refer to an object • Test: Unit_Test_Setup
Details: Autograder • Not all tests that you can see in the GUI are neccessarily graded • Failed tests are big, but passed tests are kinda small & on the bottom
Details: Autograder • Note that compromising the system in any way will get you a zero • Cracking/changing/disabling tests • WRITING CODE TO PASS A TEST, DESPITE NOT ACCOMPLISHING IT’S REAL GOAL • Ex: A ‘FindInArray’ method that just asks “Did I get asked to find the value 8? If so, return true”, so that it passes the test which asks “Is 8 in the array?”
Normal Console Program • Make sure that 03_PCE_StudentCode is the startup project • Right-click on the PROJECT, and choose “Set as Startup Project” to make it the startup project • Put whatever code you want to into the main method.
Normal Console Program • If you want, you can always create a new console solution, then copy your code into it.