Coverage for tests/test_cliOption.py : 40%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of daf_butler.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22"""Unit tests for the daf_butler dataset-type CLI option.
23"""
25import abc
26import click
27import click.testing
28import unittest
29import yaml
31from lsst.daf.butler.registry import CollectionType
32from lsst.daf.butler.cli.opt import (collection_type_option, config_file_option, config_option,
33 dataset_type_option, directory_argument, glob_parameter, verbose_option)
34from lsst.daf.butler.cli.utils import clickResultMsg
37class OptionTestBase(unittest.TestCase, abc.ABC):
39 def setUp(self):
40 self.runner = click.testing.CliRunner()
42 def run_command(self, cmd, args):
43 """
45 Parameters
46 ----------
47 cmd : click.Command
48 The command function to call
49 args : [`str`]
50 The arguments to pass to the function call.
52 Returns
53 -------
54 [type]
55 [description]
56 """
57 return self.runner.invoke(cmd, args)
59 def run_test(self, cmd, cmdArgs, verifyFunc, verifyArgs=None):
60 result = self.run_command(cmd, cmdArgs)
61 verifyFunc(result, verifyArgs)
63 def run_help_test(self, cmd, expcectedHelpText):
64 result = self.runner.invoke(cmd, ["--help"])
65 # remove all whitespace to work around line-wrap differences.
66 self.assertIn("".join(expcectedHelpText.split()), "".join(result.output.split()))
68 @property
69 @abc.abstractmethod
70 def optionClass(self):
71 pass
73 def help_test(self):
74 @click.command()
75 @self.optionClass()
76 def cli():
77 pass
79 self.run_help_test(cli, self.optionClass.defaultHelp)
81 def custom_help_test(self):
82 @click.command()
83 @self.optionClass(help="foobarbaz")
84 def cli(collection_type):
85 pass
87 self.run_help_test(cli, "foobarbaz")
90class CollectionTypeTestCase(OptionTestBase):
92 optionClass = collection_type_option
94 def setUp(self):
95 super().setUp()
96 CollectionTypeTestCase.collectionType = None
98 @staticmethod
99 @click.command()
100 @collection_type_option()
101 def cli(collection_type):
102 CollectionTypeTestCase.collectionType = collection_type
104 def verify(self, result, verifyArgs):
105 self.assertEqual(result.exit_code, 0, clickResultMsg(result))
106 self.assertEqual(CollectionTypeTestCase.collectionType, verifyArgs)
108 def test_run(self):
109 self.run_test(CollectionTypeTestCase.cli, ["--collection-type", "RUN"],
110 self.verify, CollectionType.RUN)
112 def test_chained(self):
113 self.run_test(CollectionTypeTestCase.cli, ["--collection-type", "CHAINED"],
114 self.verify, CollectionType.CHAINED)
116 def test_tagged(self):
117 self.run_test(CollectionTypeTestCase.cli, ["--collection-type", "TAGGED"],
118 self.verify, CollectionType.TAGGED)
120 def test_default(self):
121 self.run_test(CollectionTypeTestCase.cli, [],
122 self.verify, None)
124 def test_caseInsensitive(self):
125 self.run_test(CollectionTypeTestCase.cli, ["--collection-type", "TaGGeD"],
126 self.verify, CollectionType.TAGGED)
128 def test_help(self):
129 self.help_test()
130 self.custom_help_test()
133class ConfigTestCase(OptionTestBase):
135 optionClass = config_option
137 @staticmethod
138 @click.command()
139 @config_option()
140 def cli(config):
141 click.echo(yaml.dump(config), nl=False)
143 def test_basic(self):
144 """test arguments"""
145 result = self.runner.invoke(ConfigTestCase.cli, ["--config", "a=1", "-c", "b=2,c=3"])
146 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
147 self.assertEqual(yaml.safe_load(result.stdout), dict(a="1", b="2", c="3"))
149 def test_missing(self):
150 @click.command()
151 @config_option(required=True)
152 def cli(config):
153 pass
155 result = self.runner.invoke(cli, [])
156 self.assertNotEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
157 self.assertIn('Missing option "-c" / "--config"', result.output)
159 def test_help(self):
160 self.help_test()
161 self.custom_help_test()
164class ConfigFileTestCase(OptionTestBase):
166 optionClass = config_file_option
168 @staticmethod
169 @click.command()
170 @config_file_option()
171 def cli(config_file):
172 click.echo(config_file, nl=False)
174 def test_basic(self):
175 """test arguments"""
176 result = self.runner.invoke(ConfigFileTestCase.cli, ["--config-file", "path/to/file"])
177 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
178 self.assertEqual("path/to/file", result.stdout)
180 def test_missing(self):
181 @click.command()
182 @config_file_option(required=True)
183 def cli(config):
184 pass
185 result = self.runner.invoke(cli, [])
186 self.assertNotEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
187 self.assertIn('Missing option "-C" / "--config-file"', result.output)
189 def test_help(self):
190 self.help_test()
191 self.custom_help_test()
194class DatasetTypeTestCase(OptionTestBase):
196 optionClass = dataset_type_option
198 @staticmethod
199 @click.command()
200 @dataset_type_option(help="the dataset type")
201 def cli(dataset_type):
202 click.echo(dataset_type, nl=False)
204 def verify(self, result, verifyArgs):
205 self.assertEqual(result.exit_code, 0, clickResultMsg(result))
206 self.assertEqual(result.stdout, verifyArgs)
208 def test_single(self):
209 """test a single argument"""
210 self.run_test(DatasetTypeTestCase.cli, ["--dataset-type", "one"], self.verify, "['one']")
212 def test_multiple(self):
213 """test multiple arguments, using the long and short option names"""
214 self.run_test(DatasetTypeTestCase.cli, ["--dataset-type", "one", "-d", "two"],
215 self.verify, "['one', 'two']")
217 def test_singlePair(self):
218 """test a single comma-separated value pair"""
219 self.run_test(DatasetTypeTestCase.cli, ["--dataset-type", "one,two"],
220 self.verify, "['one', 'two']")
222 def test_multiplePair(self):
223 """test multiple comma-separated value pairs"""
224 self.run_test(DatasetTypeTestCase.cli, ["--dataset-type", "one,two", "-d", "three,four"],
225 self.verify, "['one', 'two', 'three', 'four']")
227 def test_help(self):
228 # dataset_type_option does not have default help
229 self.custom_help_test()
232class DirectoryArgumentTestCase(OptionTestBase):
234 optionClass = directory_argument
236 def test_required(self):
237 """test arguments"""
238 @click.command()
239 @directory_argument(required=True)
240 def cli(directory):
241 click.echo(directory, nl=False)
242 result = self.runner.invoke(cli, ["this_dir"])
243 self.assertEqual(result.exit_code, 0, clickResultMsg(result))
244 self.assertEqual("this_dir", result.stdout)
245 result = self.runner.invoke(cli, [])
246 self.assertNotEqual(result.exit_code, 0, clickResultMsg(result))
247 self.assertIn('Missing argument "DIRECTORY"', result.stdout)
249 def test_notRequired(self):
250 """test arguments"""
251 @click.command()
252 @directory_argument()
253 def cli(directory):
254 click.echo(directory, nl=False)
255 result = self.runner.invoke(cli, ["this_dir"])
256 self.assertEqual(result.exit_code, 0, clickResultMsg(result))
257 self.assertEqual("this_dir", result.stdout)
258 result = self.runner.invoke(cli, [])
259 self.assertEqual(result.exit_code, 0, clickResultMsg(result))
260 self.assertEqual("", result.stdout)
262 def test_help(self):
263 # directory_argument does not have default help.
264 self.custom_help_test()
267class GlobTestCase(OptionTestBase):
269 optionClass = glob_parameter
271 def verify(self, result, verifyArgs):
272 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
273 self.assertIn(verifyArgs, result.stdout)
275 def verifyMissing(self, result, verifyArgs):
276 self.assertNotEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
277 self.assertIn(verifyArgs, result.stdout)
279 def test_glob_argument(self):
280 """test argument"""
281 @click.command()
282 @glob_parameter(parameterType=glob_parameter.ARGUMENT)
283 def cli(glob):
284 if glob is None:
285 glob = "None"
286 print(glob)
288 self.run_test(cli, ["foo*"], self.verify, "foo*")
289 self.run_test(cli, [], self.verify, "None")
291 def test_glob_argument_required(self):
292 """test with argument required"""
293 @click.command()
294 @glob_parameter(parameterType=glob_parameter.ARGUMENT, required=True)
295 def cli(glob):
296 print(glob)
298 self.run_test(cli, ["foo*"], self.verify, "foo*")
299 self.run_test(cli, [], self.verifyMissing, 'Error: Missing argument "GLOB"')
301 def test_glob_option(self):
302 """test option"""
303 @click.command()
304 @glob_parameter()
305 def cli(glob):
306 if glob is None:
307 glob = "None"
308 print(glob)
310 self.run_test(cli, ["--glob", "foo*"], self.verify, "foo*")
311 self.run_test(cli, [], self.verify, "None")
313 def test_glob_option_required(self):
314 """test with argument required"""
315 @click.command()
316 @glob_parameter(parameterType=glob_parameter.ARGUMENT, required=True)
317 def cli(glob):
318 print(glob)
320 self.run_test(cli, ["foo*"], self.verify, "foo*")
321 self.run_test(cli, [], self.verifyMissing, 'Error: Missing argument "GLOB"')
323 def test_glob_argument_multiple(self):
324 """test with multiple argument values"""
325 @click.command()
326 @glob_parameter(parameterType=glob_parameter.ARGUMENT, multiple=True)
327 def cli(glob):
328 print(glob)
330 self.run_test(cli, ["foo*", "bar", "b?z"], self.verify, "('foo*', 'bar', 'b?z')")
332 def test_glob_option_multiple(self):
333 """test with multiple option values"""
334 @click.command()
335 @glob_parameter(multiple=True)
336 def cli(glob):
337 print(glob)
339 self.run_test(cli, ["--glob", "foo*", "--glob", "bar", "--glob", "b?z"], self.verify,
340 "('foo*', 'bar', 'b?z')")
342 def test_help(self):
343 self.help_test()
344 self.custom_help_test()
347class VerboseTestCase(OptionTestBase):
349 optionClass = verbose_option
351 @staticmethod
352 @click.command()
353 @verbose_option()
354 def cli(verbose):
355 print(verbose)
357 def verify(self, result, verifyArgs):
358 self.assertEqual(result.exit_code, 0, f"output: {result.output} exception: {result.exception}")
359 self.assertIn(verifyArgs, result.stdout)
361 def test_verbose(self):
362 """test arguments"""
363 self.run_test(self.cli, ["--verbose"], self.verify, "True")
365 def test_notVerbose(self):
366 """test arguments"""
367 self.run_test(self.cli, [], self.verify, "False")
369 def test_help(self):
370 self.help_test()
371 self.custom_help_test()
374if __name__ == "__main__": 374 ↛ 375line 374 didn't jump to line 375, because the condition on line 374 was never true
375 unittest.main()