Conditions | 49 |
Total Lines | 181 |
Lines | 0 |
Ratio | 0 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like describe_template() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | # pylint: disable=unused-variable,expression-not-assigned,misplaced-comparison-constant,singleton-comparison |
||
17 | def describe_template(): |
||
18 | |||
19 | def it_supports_comparison(): |
||
20 | t1 = Template('abc', "A Thing") |
||
21 | t2 = Template('def') |
||
22 | t3 = Template('def', "Do This") |
||
23 | |||
24 | assert t1 != t2 |
||
25 | assert t2 == t3 |
||
26 | assert t1 < t3 |
||
27 | |||
28 | def describe_get_path(): |
||
29 | |||
30 | @patch('pathlib.Path.is_file', Mock(return_value=True)) |
||
31 | def it_returns_default_when_no_style(template): |
||
32 | expect(template.get_path()) == Path("abc/default.png") |
||
33 | |||
34 | @patch('pathlib.Path.is_file', Mock(return_value=True)) |
||
35 | def it_returns_alternate_when_style_provided(template): |
||
36 | expect(template.get_path('Custom')) == Path("abc/custom.png") |
||
37 | |||
38 | @patch('pathlib.Path.is_file', Mock(return_value=True)) |
||
39 | def it_returns_default_when_style_is_none(template): |
||
40 | expect(template.get_path(None)) == Path("abc/default.png") |
||
41 | |||
42 | @patch('pathlib.Path.is_file', Mock(return_value=False)) |
||
43 | def it_considers_urls_valid_styles(template): |
||
44 | url = "http://example.com" |
||
45 | path = temp("a9b9f04336ce0181a08e774e01113b31") |
||
46 | expect(template.get_path(url)) == path |
||
47 | |||
48 | @patch('pathlib.Path.is_file', Mock(return_value=True)) |
||
49 | def it_caches_file_downloads(template): |
||
50 | url = "http://this/will/be/ignored" |
||
51 | path = temp("d888710f0697650eb68fc9dcbb976d4c") |
||
52 | expect(template.get_path(url)) == path |
||
53 | |||
54 | def it_handles_bad_urls(template): |
||
55 | expect(template.get_path("http://invalid")) == None |
||
56 | |||
57 | def it_handles_invalid_paths(template): |
||
58 | expect(template.get_path("@#$%^")) == None |
||
59 | |||
60 | def describe_path(): |
||
61 | |||
62 | def is_returned_when_file_exists(template): |
||
63 | template.root = "my_root" |
||
64 | |||
65 | with patch('pathlib.Path.is_file', Mock(return_value=True)): |
||
66 | path = template.path |
||
67 | |||
68 | expect(path) == Path("my_root/abc/default.png") |
||
69 | |||
70 | def is_none_when_no_file(template): |
||
71 | template.root = "my_root" |
||
72 | |||
73 | with patch('pathlib.Path.is_file', Mock(return_value=False)): |
||
74 | path = template.path |
||
75 | |||
76 | expect(path) == None |
||
77 | |||
78 | def describe_default_path(): |
||
79 | |||
80 | def is_based_on_lines(template): |
||
81 | expect(template.default_path) == "foo/bar" |
||
82 | |||
83 | def is_underscore_when_no_lines(template): |
||
84 | template.lines = [] |
||
85 | |||
86 | expect(template.default_path) == "_" |
||
87 | |||
88 | def describe_styles(): |
||
89 | |||
90 | @patch('os.listdir', Mock(return_value=[])) |
||
91 | def is_empty_when_no_alternate_images(template): |
||
92 | expect(template.styles) == [] |
||
93 | |||
94 | @patch('os.listdir', Mock(return_value=['foo.jpg', 'bar.png'])) |
||
95 | def is_filesnames_of_alternate_images(template): |
||
96 | expect(template.styles) == ['bar', 'foo'] |
||
97 | |||
98 | def describe_sample_path(): |
||
99 | |||
100 | def is_based_on_lines(template): |
||
101 | expect(template.sample_path) == "foo/bar" |
||
102 | |||
103 | def is_placeholder_when_no_lines(template): |
||
104 | template.lines = [] |
||
105 | |||
106 | expect(template.sample_path) == "your_text/goes_here" |
||
107 | |||
108 | def describe_keywords(): |
||
109 | |||
110 | def is_the_set_of_all_relevant_terms(template): |
||
111 | template.lines[0] = "A day in the life" |
||
112 | |||
113 | expect(template.keywords) == \ |
||
114 | {'bar', 'the', 'day', 'in', 'abc', 'a', 'life'} |
||
115 | |||
116 | def describe_search(): |
||
117 | |||
118 | def it_counts_contained_terms(template): |
||
119 | template.key = 'Foo' |
||
120 | template.name = "The Foobar Meme" |
||
121 | template.aliases.append('Foo') |
||
122 | template.aliases.append('Foobar') |
||
123 | template.lines[0] = "This on time foobar happened" |
||
124 | |||
125 | expect(template.search("Foo")) == 5 |
||
126 | |||
127 | def it_treats_none_specially(template): |
||
128 | expect(template.search(None)) == -1 |
||
129 | |||
130 | def describe_validate_meta(): |
||
131 | |||
132 | def with_no_name(template): |
||
133 | template.name = None |
||
134 | |||
135 | expect(template.validate_meta()) == False |
||
136 | |||
137 | def with_no_default_image(template): |
||
138 | expect(template.validate_meta()) == False |
||
139 | |||
140 | def with_nonalphanumberic_name(template): |
||
141 | template.name = "'ABC' Meme" |
||
142 | |||
143 | expect(template.validate_meta()) == False |
||
144 | |||
145 | def describe_validate_link(): |
||
146 | |||
147 | @pytest.fixture(autouse=True) |
||
148 | def enable_validation(monkeypatch): |
||
149 | monkeypatch.setenv('VALIDATE_LINKS', "true") |
||
150 | |||
151 | def with_bad_link(template): |
||
152 | mock_response = Mock() |
||
153 | mock_response.status_code = 404 |
||
154 | |||
155 | with patch('requests.head', Mock(return_value=mock_response)): |
||
156 | template.link = "example.com/fake" |
||
157 | |||
158 | expect(template.validate_link(delay=0)) == False |
||
159 | |||
160 | @patch('pathlib.Path.is_file', Mock(return_value=True)) |
||
161 | def with_cached_valid_link(template): |
||
162 | template.link = "already_cached_site.com" |
||
163 | |||
164 | expect(template.validate_link(delay=0)) == True |
||
165 | |||
166 | def describe_validate_size(): |
||
167 | |||
168 | @pytest.mark.parametrize('dimensions,valid', [ |
||
169 | ((Template.MIN_WIDTH, Template.MIN_HEIGHT), True), |
||
170 | ((Template.MIN_WIDTH - 1, Template.MIN_HEIGHT), False), |
||
171 | ((Template.MIN_WIDTH, Template.MIN_HEIGHT - 1), False), |
||
172 | ((Template.MIN_WIDTH - 1, Template.MIN_HEIGHT - 1), False), |
||
173 | ]) |
||
174 | @patch('PIL.Image.open') |
||
175 | def with_various_dimenions(mock_open, template, dimensions, valid): |
||
176 | mock_img = Mock() |
||
177 | mock_img.size = dimensions |
||
178 | mock_open.return_value = mock_img |
||
179 | |||
180 | expect(template.validate_size()) == valid |
||
181 | |||
182 | def describe_validate(): |
||
183 | |||
184 | def with_no_validators(template): |
||
185 | expect(template.validate([])) == True |
||
186 | |||
187 | def with_all_passing_validators(template): |
||
188 | """Verify a template is valid if all validators pass.""" |
||
189 | mock_validators = [lambda: True] |
||
190 | |||
191 | expect(template.validate(validators=mock_validators)) == True |
||
192 | |||
193 | def with_one_failing_validator(template): |
||
194 | """Verify a template is invalid if any validators fail.""" |
||
195 | mock_validators = [lambda: False] |
||
196 | |||
197 | expect(template.validate(validators=mock_validators)) == False |
||
198 |