On Sun, Dec 8, 2013 at 8:22 PM, Rafael Knuth <rafael.kn...@gmail.com> wrote: > Hey there, > > I struggle to understand what unit testing specifically means in > practice and how to actually write unit tests for my code (my gut is > telling me that it's a fairly important concept to understand).
Your gut feeling is right. However, you will only *truly* understand it's usefulness as you write more programs yourself. No matter how many articles or blog posts or books you read it in, it's something which you will yourself have to "realize" and once you do so, you will find great value in it. Also, don't fret if you don't realize it. You will, sooner or latter. Here is a fairly common use case where you will really find tests useful (try it!): Say, you have a fairly big program, single file (module) or spread across multiple files. Now, as you improve your understanding, you realize that you can write more efficient/elegant code. So you go on a wholesale refactoring spree (the technical term for changing your existing code to cleanup your existing code to write more optimized or idiomatic code). However, you are not very confident that all the changes haven't broken any of your existing features. So, what do you do? When you don't have tests, you have to manually imagine and run the programs for all possible inputs and check if the output/results are as expected. On the other hand, if you have a tests, you can simply run these tests and refactor your code confidently. However, I have also realized during my own learning adventures and learning from the existing code base and users' bug reports that the benefit of tests are solely dependent on the the "test cases" you have covered in your tests. If you missed a scenario (a test case) in your tests, then it is likely that any breakage of functionality in that area of your program will not be undetected when you run the tests. > > Over the last few days I learned how to write and work with classes, I > learned quite a lot about functions, nested loops and I currently walk > through every program in the Python.org wiki "Simple Programs" > https://wiki.python.org/moin/SimplePrograms ... and here's the unit > test program they provide: > > import unittest > def median(pool): > copy = sorted(pool) > size = len(copy) > if size % 2 == 1: > return copy[(size - 1) / 2] > else: > return (copy[size/2 - 1] + copy[size/2]) / 2 BTW, this program will not work in Python 3, since a division operation returns a float. so, 4/2 = 2.0 . > class TestMedian(unittest.TestCase): > def testMedian(self): > self.failUnlessEqual(median([2, 9, 9, 7, 9, 2, 4, 5, 8]), 7) > if __name__ == '__main__': > unittest.main() > > Also, I went through the "Beginning Test-Driven Development in Python" > http://net.tutsplus.com/tutorials/python-tutorials/test-driven-development-in-python/ > but I have to admit I still don't fully understand how unit tests work > in practice and how to write my own unit tests. I will attempt an explanation with a far simpler function: # myarith.py def sum(a,b): return a+b Let's say you have saved this function in a module, myarith.py. Now, how would you really verify if the function actually returns the sum of the numbers passed to it? By calling the function of course. Here is one way: >>> import myarith >>> myarith.sum(1, 2) 3 >>> myarith.sum(1, 5) 6 >>> myarith.sum(-11, -5) -16 test case So, you are confident that your function works as expected. Now, instead of calling your function as above, you want to use the unittest module. Here is a test module which tests the above function: # test_arith.py import unittest import myarith class ArithTest(unittest.TestCase): def test_sum(self): self.assertEqual(myarith.sum(1,2), 1+2) if __name__ == '__main__': unittest.main() We first create a class ArithTest which is a subclass of unittest.TestCase. This means that, the class ArithTest is a test case and in it you will have various tests to test the functions in your myarith module. Right now, there is only one function, sum(). So, we create a function, test_sum() where we call the sum() function as above, but we call it inside the assertEqual() method which basically tests whether the first argument's value is equal to the second argument. Now, when you run this module, you will see something like: $ python3 test_arith.py . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK Now, let us modify the test_sum() method: import unittest import myarith class ArithTest(unittest.TestCase): def test_sum(self): self.assertEqual(myarith.sum(1,2), 1+2) def test_sum_2(self): self.assertEqual(myarith.sum(2,2), 15) if __name__ == '__main__': unittest.main() A new test has been added, test_sum_2() which is obviously going to fail. Let's see what happens when we run the module again: .F ====================================================================== FAIL: test_sum_2 (__main__.ArithTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_arith.py", line 10, in test_sum_2 self.assertEqual(myarith.sum(2,2), 15) AssertionError: 4 != 15 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) So, it tells us that two tests were ran and one of them failed. > > As it turned out over the last few weeks, the best modus operandi for > me as an absolute beginner is to grab a small program, take it apart > in the first place, understand how each component works through trial > & error, then put all those pieces together and then I kind of get the > big picture. Once I "get it" I practice as much as possible to > memorize what I just learned and *then* I start readying as many > blogs, tutorials etc. as possible to deepen my understanding (I > frankly find most tutorials & blogs too complex and confusing from a > beginner's viewpoint, and I learn faster by taking code apart and > learning through trial & error in the first place). So, what I am > specifically searching for is a very simple code sample which I can > take apart and iterate through each component, and I was wondering if > you are aware of resources that might be helpful? Does the above example help? > > My understanding of unit testing is that I have to embed my code into > a test and then I have to define conditions under which my code is > supposed to fail and pass. Is that assumption correct? Almost. However, as you can see from the above example that you need not write tests in the same file as the code you are testing. You define a set of input scenarios and check if your program is behaving as expected. Sometimes, the behavior is returning the correct value, and other times, your program should error out gracefully. If you have been able to understand a little bit more, I would also suggest you to take a look at CPython's tests for lists: http://hg.python.org/releasing/3.3.3/file/b34363761e4c/Lib/test/test_list.py as an example of the kind of things you should look to test and how they may be done. > > I am a bit lost & confused here .. any help & hing is highly appreciated! > > Thank you & all the best, I hope I have been able to make it a little better for you. Good luck. Best, Amit. -- http://echorand.me _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor