Hide keyboard shortcuts

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/>. 

21 

22import abc 

23import copy 

24import os 

25 

26from ..cli.utils import clickResultMsg, mockEnvVar, LogCliRunner, Mocker 

27from ..cli import butler 

28 

29 

30class CliCmdTestBase(abc.ABC): 

31 """A test case base that is used to verify click command functions import 

32 and call their respective script fucntions correctly. 

33 """ 

34 

35 @classmethod 

36 @property 

37 @abc.abstractmethod 

38 def defaultExpected(cls): 

39 pass 

40 

41 @classmethod 

42 @property 

43 @abc.abstractmethod 

44 def command(cls): 

45 """Get the click.Command being tested.""" 

46 pass 

47 

48 @property 

49 def cli(self): 

50 """Get the command line interface function under test, can be 

51 overridden to test CLIs other than butler.""" 

52 return butler.cli 

53 

54 def setUp(self): 

55 self.runner = LogCliRunner(env=mockEnvVar) 

56 

57 def makeExpected(self, **kwargs): 

58 expected = copy.copy(self.defaultExpected) 

59 expected.update(kwargs) 

60 return expected 

61 

62 def run_command(self, inputs): 

63 """Use the LogCliRunner with the mock environment variable set to 

64 execute a butler subcommand and parameters specified in inputs. 

65 

66 Parameters 

67 ---------- 

68 inputs : [`str`] 

69 A list of strings that begins with the subcommand name and is 

70 followed by arguments, option keys and option values. 

71 

72 Returns 

73 ------- 

74 result : `click.testing.Result` 

75 The Result object contains the results from calling 

76 self.runner.invoke. 

77 """ 

78 return self.runner.invoke(self.cli, inputs) 

79 

80 def run_test(self, inputs, expectedKwargs, withTempFile=None): 

81 """Run the subcommand specified in inputs and verify a successful 

82 outcome where exit code = 0 and the mock object has been called with 

83 the expected arguments. 

84 

85 Returns the result object for inspection, e.g. sometimes it's useful to 

86 be able to inpsect or print `result.output`. 

87 

88 Parameters 

89 ---------- 

90 inputs : [`str`] 

91 A list of strings that begins with the subcommand name and is 

92 followed by arguments, option keys and option values. 

93 expectedKwargs : `dict` [`str`, `str`] 

94 The arguments that the subcommand function is expected to have been 

95 called with. Keys are the argument name and values are the argument 

96 value. 

97 withTempFile : `str`, optional 

98 If not None, will run in a temporary directory and create a file 

99 with the given name, can be used with commands with parameters that 

100 require a file to exist. 

101 

102 Returns 

103 ------- 

104 result : `click.testing.Result` 

105 The result object produced by invocation of the command under test. 

106 """ 

107 with self.runner.isolated_filesystem(): 

108 if withTempFile is not None: 

109 os.makedirs(os.path.dirname(withTempFile), exist_ok=True) 

110 with open(withTempFile, "w") as _: 

111 pass 

112 result = self.run_command(inputs) 

113 self.assertEqual(result.exit_code, 0, clickResultMsg(result)) 

114 Mocker.mock.assert_called_with(**expectedKwargs) 

115 return result 

116 

117 def run_missing(self, inputs, expectedMsg): 

118 """Run the subcommand specified in inputs and verify a failed outcome 

119 where exit code != 0 and an expected message has been written to 

120 stdout. 

121 

122 Parameters 

123 ---------- 

124 inputs : [`str`] 

125 A list of strings that begins with the subcommand name and is 

126 followed by arguments, option keys and option values. 

127 expectedMsg : `str` 

128 An error message that should be present in stdout after running the 

129 subcommand. 

130 """ 

131 result = self.run_command(inputs) 

132 self.assertNotEqual(result.exit_code, 0, clickResultMsg(result)) 

133 self.assertIn(expectedMsg, result.stdout) 

134 

135 def test_help(self): 

136 self.assertFalse(self.command.get_short_help_str().endswith("..."), 

137 msg="The command help message is being truncated to " 

138 f"\"{self.command.get_short_help_str()}\". It should be shortened, or define " 

139 "@command(short_help=\"something short and helpful\")")