Code Testing#
Q&A
Q: How can I link pandas t google sheets and how could one write there own methods for pandas?
A: There is an additional package that most people use to read directly from googlesheets (calledgspread
) [I will note that in R this is a bit more straightforward than in python, but that’s neither here nor thtere.] As for writing your own methods, the most typical way would be to write a new class that inherits from the pandas object (for example a DataFrame) and adds additional methods - we briefly touched on inheritance. That said, while it’s possible, pandas has a TON of methods so it’s rare that you’d need to write one on your own.
Q: how familiar should we be with setting up an array ourselves?
A: Understand it conceptually, but you don’t need to memorize the syntax to do so.
Q: I was confused on the practice problem we worked on when it mentioned 3x3, I was just wondering whenever we see something like this is it basically telling us we have to create 3 lists inside of one list?
A: Kind of. 3x3 indicates the rows and columns. So 4x2 would be 4 rows (the first number) and 2 columns (the second number)
Q: I’m still a bit unsure about when to use NumPy vs. pandas, and how to choose the right one when working with data. Also, I’d like more practice with writing and running scripts from the terminal.
A: If you’re doing linear algebra/matrix math, numpy. Otherwise, if working with a dataset that you want to do some analysis on, it’s almost always pandas. Your final exam will focus on pandas (As will your A5). We introduce numpy to lay the foundation for discussing pandas.
Q: Also, I’d like more practice with writing and running scripts from the terminal.
A: We’ll do more of this next week!
Q: What specific topics from scientific computing will we need to know for the final exam?
A: Familiarity with numpy and pandas (their goals, main objects, etc.) and the ability to interact with pandas DataFrame objects. You do not need to memorize available methods, but if I tell you what methods do, you need to know how to use them.
Course Announcements
Due this week:
CL8 due Fri
A5 due Sun
Complete E2
Notes:
Please complete your SETs (especially for TAs/IAs) by 8AM Sat
Retest (E1 or E2) will be available on PrairieTest tomorrow Fri 5/30
Reminder to complete the Food Insecurity Survey (by Friday)
Final Exam#
There will a handful of MC and SA questions
The bulk of the exam will be a “mini project” focused on the material since E2. This will involve:
Debugging a function or two; these will use pandas/interact with data
These will be stored in a module (.py file)
maybe writing/executing a script that uses these functions
Writing a test function or two using
unittest
(we’re discussing this today!)using good code style
There will be a practice exam. We will discuss putting all of these pieces together in class next week.
Code Testing#
Motivation
Some Testing Practices
unittest
FundamentalsTry It Out!
Code Testing: a process to ensure that your code runs correctly
Part I: Motivation#
Why should we test our code?
Writing Good Code#
All in all, write code that is:
Well organized (follows a style guide)
Tested
Documented
And you will have understandable, maintainable, and trustable code.
Four Types of Code Testing#
Unit tests (primary focus): test functions & objects to ensure that the code is behaving as expected
Smoke tests: preliminary tests to check basic functionality; checks if something runs, but not necessarily if it does the right thing (gut check)
Integration tests: test functions, classes & modules interacting
System tests: tests end-to-end behavior
Unit Tests#
One test for each “piece” of your code (function, class, etc.)
unittest
will let you know which tests pass/fail/throw an errorTesting “edge (atypical) cases”
Help you resist the urge to assume computers will act how you think it will work
Part II: Some Testing Practices#
How to Write Tests#
Given a function or class you want to test:
You need to have an expectation for what it should do
Write out some example cases, with known answers
Use assert to check that your example cases do run as expected
Collect these examples into test functions, stored in test files
Test Driven Development#
In software development, test-driven development is an approach in which you write tests first - and then write code to pass the tests.
Ensures you go into writing code with a good plan / outline
Ensures that you have a test suite, as you can not decide to neglect to test your code after the fact you made the test suite
Note: when you complete (or at least write) assignments for this class, you are effectively doing test-driven development
Activity 1: Code Testing Ideas#
Please complete the following Google Form: https://forms.gle/86dnUZ7yd88trCUd8
Part III: unittest
Fundamentals#
The very first step is to import the unittest
framework.
import unittest
General template for testing in unittest
:#
class TestName(unittest.TestCase):
# TEST FUNCTIONS BELONG INSIDE THE CLASS
def test_name_1(self):
# code statements go inside here
self.assertEqual(1, 1)
def test_name_2(self):
# code statements go inside here
self.assertTrue(False)
# ...
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestName)
unittest.TextTestRunner(verbosity=2).run(suite)
Some testing functions in unittest
:#
.assertEqual(a, b)
#
Checks if a
is equal to b
. Similar to the expression a == b
.
Note: Although it doesn’t affect the results, it’s good practice to let a
be the expected value (what you think the result will be) and b
be the actual value (what the result actually is).
def add(a, b):
return a + b
# Equality testing suite
class TestEqual(unittest.TestCase):
# First test
def test_equal(self):
self.assertEqual(10, add(4, 6))
# Second test
def test_equal_bad(self):
self.assertEqual(11, add(4, 6))
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestEqual)
unittest.TextTestRunner(verbosity=2).run(suite)
.assertTrue(x)
#
Checks if x
is True
. Same as the expression bool(x) == True
.
# Truth testing suite
class TestTrue(unittest.TestCase):
def test_true(self):
self.assertTrue(add(4, 6) == 10)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestTrue)
unittest.TextTestRunner(verbosity=2).run(suite)
.assertFalse(x)
#
Checks if x
is False
. Same as the expression bool(x) == False
.
# False testing suite
class TestFalse(unittest.TestCase):
def test_false(self):
self.assertFalse(add(4, 6) == 11)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestFalse)
unittest.TextTestRunner(verbosity=2).run(suite)
.assertIsInstance(a, b)
#
Checks if a
is of variable type b
(int, float, str, bool) or is of an instance of class b
. Similar to the expression isinstance(a, b)
or type(a) == b
.
# Instance testing suite
class TestInstances(unittest.TestCase):
# First test
def test_instance(self):
self.assertIsInstance('Hello!', str)
# Second test
def test_instance_bad(self):
self.assertIsInstance(3.14, int)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestInstances)
unittest.TextTestRunner(verbosity=2).run(suite)
.assertIsNone(x)
#
Checks if x
is None
. Similar to the expression x is None
.
def return_none():
return
# None testing suite
class TestNone(unittest.TestCase):
# First test
def test_none_1(self):
self.assertIsNone(return_none())
# Second test
def test_none_append(self):
lst = []
self.assertIsNone(lst.append(1))
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestNone)
unittest.TextTestRunner(verbosity=2).run(suite)
.assertIn(a, b)
#
Checks for membership, if a
belongs in b
. Same as the expression a in b
.
# Membership testing suite
class TestIn(unittest.TestCase):
fruits = ['apples', 'bananas', 'oranges']
# First test
def test_membership(self):
self.assertIn('apples', self.fruits)
# Second test
def test_membership_bad(self):
self.assertIn('pears', self.fruits)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestIn)
unittest.TextTestRunner(verbosity=2).run(suite)
Putting it all together…#
class TestAllAdd(unittest.TestCase):
def test_all(self):
self.assertEqual(10, add(4, 6))
self.assertEqual(11, add(4, 6))
self.assertTrue(add(4, 6) == 10)
self.assertFalse(add(4, 6) == 11)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestAllAdd)
unittest.TextTestRunner(verbosity=2).run(suite)
Part IV: Try It Out!#
Make a class named Person
that has two instance attributes: name
and age
. Be sure that they are assigned to user-specified values.
Then, make a method called birthday()
that increments age
by 1 and returns the string “Happy Birthday!”
Then, create a test class with only one test function that does the following:
Create an instance of the
Person
classWrite the following tests, making sure that they pass:
The instance is of instance
Person
The instance’s name is equal to the name you gave it
The instance’s age is equal to the age you gave it
Call the
birthday()
function and write a test checking if the instance’s age got incremented by 1
Submit your responses to this Google Form: https://forms.gle/mRY9zxSxGFuSY6A38
# TRY IT OUT