Presentation is loading. Please wait.

Presentation is loading. Please wait.

Interface and Implementation Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Similar presentations


Presentation on theme: "Interface and Implementation Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See"— Presentation transcript:

1 Interface and Implementation Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See http://software-carpentry.org/license.html for more information. Testing

2 Interface and Implementation One of the most important ideas in computing is the difference between interface and implementation

3 TestingInterface and Implementation One of the most important ideas in computing is the difference between interface and implementation Interface: how something interacts with the world

4 TestingInterface and Implementation One of the most important ideas in computing is the difference between interface and implementation Interface: how something interacts with the world Implementation: how it does what it does

5 TestingInterface and Implementation One of the most important ideas in computing is the difference between interface and implementation Interface: how something interacts with the world Implementation: how it does what it does def integrate(func, x1, x2):...math goes here... return result

6 TestingInterface and Implementation One of the most important ideas in computing is the difference between interface and implementation Interface: how something interacts with the world Implementation: how it does what it does def integrate(func, x1, x2):...math goes here... return result Interface: (f, x 1, x 2 ) -> integral

7 TestingInterface and Implementation One of the most important ideas in computing is the difference between interface and implementation Interface: how something interacts with the world Implementation: how it does what it does def integrate(func, x1, x2):...math goes here... return result Interface: (f, x 1, x 2 ) -> integral Implementation: we don't (have to) care

8 TestingInterface and Implementation Often use this idea to simplify unit testing

9 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one

10 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one But components depend on each other

11 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one But components depend on each other How to isolate the component under test from other components?

12 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one But components depend on each other How to isolate the component under test from other components? Replace the other components with things that have the same interfaces, but simpler implementations

13 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one But components depend on each other How to isolate the component under test from other components? Replace the other components with things that have the same interfaces, but simpler implementations Sometimes requires refactoring

14 TestingInterface and Implementation Often use this idea to simplify unit testing Want to test components in program one by one But components depend on each other How to isolate the component under test from other components? Replace the other components with things that have the same interfaces, but simpler implementations Sometimes requires refactoring Or some up-front design

15 TestingInterface and Implementation Back to those fields in Saskatchewan...

16 TestingInterface and Implementation Test function that reads a photo from file

17 TestingInterface and Implementation Test function that reads a photo from file def read_photo(filename): result = set() reader = open(filename, 'r') …fill result with rectangles in file… reader.close() return result

18 TestingInterface and Implementation Test function that reads a photo from file def read_photo(filename): result = set() reader = open(filename, 'r') …fill result with rectangles in file… reader.close() return result def test_photo_containing_only_unit(): assert read_photo('unit.pht') == { ((0, 0), (1, 1)) }

19 TestingInterface and Implementation Experience teaches that this is a bad idea

20 TestingInterface and Implementation Experience teaches that this is a bad idea 1. External files can easily be misplaced

21 TestingInterface and Implementation Experience teaches that this is a bad idea 1. External files can easily be misplaced 2. Hard to understand test if fixture stored elsewhere

22 TestingInterface and Implementation Experience teaches that this is a bad idea 1. External files can easily be misplaced 2. Hard to understand test if fixture stored elsewhere 3. File I/O is much slower than memory operations

23 TestingInterface and Implementation Experience teaches that this is a bad idea 1. External files can easily be misplaced 2. Hard to understand test if fixture stored elsewhere 3. File I/O is much slower than memory operations The longer tests take to run, the less often they will be run

24 TestingInterface and Implementation Experience teaches that this is a bad idea 1. External files can easily be misplaced 2. Hard to understand test if fixture stored elsewhere 3. File I/O is much slower than memory operations The longer tests take to run, the less often they will be run And the more often developers will have to backtrack to find and fix bugs

25 TestingInterface and Implementation Original function def count_rect(filename): reader = open(filename, 'r') count = 0 for line in reader: count += 1 reader.close() return count

26 TestingInterface and Implementation Original function One rectangle per line, no comments or blank lines def count_rect(filename): reader = open(filename, 'r') count = 0 for line in reader: count += 1 reader.close() return count

27 TestingInterface and Implementation Original function One rectangle per line, no comments or blank lines Real counter would be more sophisticated def count_rect(filename): reader = open(filename, 'r') count = 0 for line in reader: count += 1 reader.close() return count

28 TestingInterface and Implementation Refactored def count_rect_in(reader): count = 0 for line in reader: count += 1 return count def count_rect(filename): reader = open(filename, 'r') result = count_rect_in(reader) reader.close() return result

29 TestingInterface and Implementation Refactored Does the work, but does not open the file def count_rect_in(reader): count = 0 for line in reader: count += 1 return count def count_rect(filename): reader = open(filename, 'r') result = count_rect_in(reader) reader.close() return result

30 TestingInterface and Implementation Refactored Opens the file def count_rect_in(reader): count = 0 for line in reader: count += 1 return count def count_rect(filename): reader = open(filename, 'r') result = count_rect_in(reader) reader.close() return result

31 TestingInterface and Implementation Refactored Opens the file Keeps name of original function def count_rect_in(reader): count = 0 for line in reader: count += 1 return count def count_rect(filename): reader = open(filename, 'r') result = count_rect_in(reader) reader.close() return result

32 TestingInterface and Implementation Now write tests

33 TestingInterface and Implementation Now write tests from StringIO import StringIO Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' def test_num_rect(): reader = StringIO(Data) assert count_rect(reader) == 3

34 TestingInterface and Implementation Now write tests A "file" that tests can be run on from StringIO import StringIO Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' def test_num_rect(): reader = StringIO(Data) assert count_rect(reader) == 3

35 TestingInterface and Implementation Now write tests Acts like a file, but uses a string in memory for storage from StringIO import StringIO Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' def test_num_rect(): reader = StringIO(Data) assert count_rect(reader) == 3

36 TestingInterface and Implementation Now write tests Doesn't know it isn't reading from a real file from StringIO import StringIO Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' def test_num_rect(): reader = StringIO(Data) assert count_rect(reader) == 3

37 TestingInterface and Implementation Use the same method to test output

38 TestingInterface and Implementation Use the same method to test output Write to a StringIO

39 TestingInterface and Implementation Use the same method to test output Write to a StringIO Use getvalue to get and check its final contents

40 TestingInterface and Implementation def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } writer = StringIO() photo_write(fixture, writer) result = writer.getvalue() assert result == '0 0 1 1\n' Use the same method to test output Write to a StringIO Use getvalue to get and check its final contents

41 TestingInterface and Implementation Use the same method to test output Write to a StringIO Use getvalue to get and check its final contents Doesn't know it isn't reading from a real file def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } writer = StringIO() photo_write(fixture, writer) result = writer.getvalue() assert result == '0 0 1 1\n'

42 TestingInterface and Implementation Use the same method to test output Write to a StringIO Use getvalue to get and check its final contents Get everything written to the StringIO as a string def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } writer = StringIO() photo_write(fixture, writer) result = writer.getvalue() assert result == '0 0 1 1\n'

43 TestingInterface and Implementation One more task

44 TestingInterface and Implementation def photo_write(photo, writer): contents = list(photo) contents.sort() for rect in contents: print >> writer, rect[0][0], rect[0][1], rect[1][0], rect[1][1] One more task

45 TestingInterface and Implementation One more task Why do the extra work of sorting? def photo_write(photo, writer): contents = list(photo) contents.sort() for rect in contents: print >> writer, rect[0][0], rect[0][1], rect[1][0], rect[1][1]

46 TestingInterface and Implementation One more task Why do the extra work of sorting? def photo_write(photo, writer): contents = list(photo) contents.sort() for rect in contents: print >> writer, rect[0][0], rect[0][1], rect[1][0], rect[1][1]

47 TestingInterface and Implementation def photo_write(photo, writer): for rect in photo: print >> writer, rect[0][0], rect[0][1], rect[1][0], rect[1][1] This version is simpler and faster

48 TestingInterface and Implementation This version is simpler and faster But there is no way to predict its output! def photo_write(photo, writer): for rect in photo: print >> writer, rect[0][0], rect[0][1], rect[1][0], rect[1][1]

49 TestingInterface and Implementation

50 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …)

51 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1

52 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1 0 0 1 1

53 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1 0 0 1 1 ≠

54 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1 0 0 1 1 ≠ Sets are unordered

55 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1 0 0 1 1 ≠ Sets are unordered Set elements are stored in an arbitrary order

56 TestingInterface and Implementation two_fields = { ((0, 0), (1, 1)), ((1, 0), (2, 1)) } photo_write(two_fields, …) 0 0 1 1 1 0 2 1 0 0 1 1 ≠ Sets are unordered Set elements are stored in an arbitrary order We can't test if we can't predict the result

57 TestingInterface and Implementation Our existing tests are inconsistent

58 TestingInterface and Implementation # From input test Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' Our existing tests are inconsistent

59 TestingInterface and Implementation # From input test Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' # From output test def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } … assert result == '0 0 1 1\n' Our existing tests are inconsistent

60 TestingInterface and Implementation Our existing tests are inconsistent # From input test Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' # From output test def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } … assert result == '0 0 1 1\n'

61 TestingInterface and Implementation Our existing tests are inconsistent Do photo files have a newline at the end of the last line or not? # From input test Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' # From output test def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } … assert result == '0 0 1 1\n'

62 TestingInterface and Implementation Our existing tests are inconsistent Do photo files have a newline at the end of the last line or not? Either answer is better than "maybe" # From input test Data = '''0 0 1 1 1 0 2 1 2 0 3 1''' # From output test def test_write_unit_only(): fixture = { ((0, 0), (1, 1)) } … assert result == '0 0 1 1\n'

63 TestingInterface and Implementation Have to design for test

64 TestingInterface and Implementation Have to design for test Depend on interface, not implementation

65 TestingInterface and Implementation Have to design for test Depend on interface, not implementation – So it's easy to replace other components for testing

66 TestingInterface and Implementation Have to design for test Depend on interface, not implementation – So it's easy to replace other components for testing – And tests don't have to be rewritten over and over

67 TestingInterface and Implementation Have to design for test Depend on interface, not implementation – So it's easy to replace other components for testing – And tests don't have to be rewritten over and over Isolate interactions with outside world

68 TestingInterface and Implementation Have to design for test Depend on interface, not implementation – So it's easy to replace other components for testing – And tests don't have to be rewritten over and over Isolate interactions with outside world – Like opening files

69 TestingInterface and Implementation Have to design for test Depend on interface, not implementation – So it's easy to replace other components for testing – And tests don't have to be rewritten over and over Isolate interactions with outside world – Like opening files Make things you are going to examine deterministic

70 August 2010 created by Greg Wilson Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See http://software-carpentry.org/license.html for more information.


Download ppt "Interface and Implementation Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See"

Similar presentations


Ads by Google