Coverage for tests/test_mod.py: 100%

43 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-09 18:59 +0200

1""" 

2Tests of :mod:`pyyc.mod` functions, to be run with :pypi:`pytest`:: 

3 

4 $ pytest -v test_mod.py 

5 

6Ideally, each function and use case should be tested: standard use (as 

7described in documentation), invalid use (handled with documented exceptions), 

8corner cases, etc. 

9 

10* :doc:`@pytest.mark.parametrize <pytest:how-to/parametrize>` decorator allows 

11 to test different inputs/outputs; 

12* :doc:`capsys <pytest:how-to/capture-stdout-stderr>` captures standard 

13 and error outputs (e.g. from :func:`print`); 

14* :doc:`monkeypatch <pytest:how-to/monkeypatch>` overrides modules and 

15 environments (e.g. :func:`input`). 

16 

17.. Note:: Some tiny parts of the code are voluntarily left untested to 

18 be used as example in `coverage report`. 

19""" 

20 

21import pytest 

22import pyyc 

23 

24 

25def test_version(): 

26 """ 

27 Simple test. 

28 """ 

29 

30 assert pyyc.mod.version == "top-level module" 

31 

32 

33def test_addition_int_list(): 

34 """ 

35 Single test of :func:`pyyc.mod.addition` on list of int. 

36 """ 

37 

38 assert pyyc.mod.addition(1, 2) == 3 

39 

40 

41def test_addition_str_list(): 

42 """ 

43 Single test of :func:`pyyc.mod.addition` on list of str. 

44 """ 

45 

46 assert pyyc.mod.addition("abc", "def") == "abcdef" 

47 

48 

49@pytest.mark.parametrize( 

50 "test_input, expected_output", 

51 [ 

52 # Test on int args 

53 ([1], 1), 

54 ([1, 2], 3), 

55 ([1, 2, 3], 6), 

56 # Test on str args 

57 (["abc"], "abc"), 

58 (["abc", "def"], "abcdef"), 

59 # Test on list args 

60 ([[1, 2]], [1, 2]), 

61 ([[1, 2], [3, 4]], [1, 2, 3, 4]), 

62 ], 

63) 

64def test_addition(test_input, expected_output): 

65 """ 

66 Test standard usage of :func:`pyyc.mod.addition`. 

67 

68 This test uses parametrization of arguments, see 

69 :doc:`pytest:how-to/parametrize`. 

70 

71 .. Tip:: `addition(*args)` will unpack the arguments on-the-fly and is 

72 similar to `addition(args[0], args[1], ...)`. 

73 """ 

74 

75 assert pyyc.mod.addition(*test_input) == expected_output 

76 

77 

78@pytest.mark.parametrize( 

79 "test_input", 

80 [ 

81 # Both entries should raise TypeError 

82 (1, "toto"), 

83 ("toto", 1) 

84 ], 

85) 

86def test_addition_TypeError(test_input): 

87 """ 

88 Test incompatible argument case. 

89 

90 It should raise :exc:`TypeError`, as mentioned in documentation of 

91 :func:`pyyc.mod.addition`. 

92 """ 

93 

94 with pytest.raises(TypeError): 

95 pyyc.mod.addition(*test_input) 

96 

97 

98def test_addition_empty(): 

99 """ 

100 Test no argument case. 

101 

102 It should raise :exc:`IndexError`, not documented. 

103 """ 

104 

105 with pytest.raises(IndexError): 

106 pyyc.mod.addition() 

107 

108# The following tests are intentionally commented out to simulate untested 

109# functions (and incomplete test coverage). 

110 

111# @pytest.mark.parametrize( 

112# "test_input, expected_output", [([1], 1), ([1.2, 2.3], 3), ([1, 2, 3], 6)] 

113# ) 

114# def test_addition_int(test_input, expected_output): 

115# """ 

116# Test standard usage of :func:`pyyc.mod.addition_int`. 

117# """ 

118 

119# assert pyyc.mod.addition_int(*test_input) == expected_output 

120 

121 

122# @pytest.mark.parametrize("test_input", [["1.2"], ["abc"]]) 

123# def test_addition_int_ValueError(test_input): 

124# """ 

125# Test non-int argument case. 

126 

127# It should raise :exc:`ValueError`, as mentioned in documentation of 

128# :func:`pyyc.mod.addition_int`. 

129# """ 

130 

131# with pytest.raises(ValueError): 

132# pyyc.mod.addition_int(*test_input) 

133 

134 

135def test_read_config_version(): 

136 """ 

137 Test a single value in configuration file. 

138 """ 

139 

140 cfg = pyyc.mod.read_config() 

141 assert cfg["DEFAULT"]["version"] == "cfg-1.0" 

142 

143 

144def test_read_config_content(capsys): 

145 """ 

146 Test full content of configuration file. 

147 

148 This test uses stdout capture, see :doc:`pytest:how-to/capture-stdout-stderr`. 

149 """ 

150 

151 import sys 

152 

153 cfg = pyyc.mod.read_config() 

154 captured = capsys.readouterr() # Capture standard & error outputs (not used) 

155 cfg.write(sys.stdout) # Write config to stdout 

156 captured = capsys.readouterr() # Capture standard & error outputs 

157 assert captured.out == "[DEFAULT]\nversion = cfg-1.0\n\n" 

158 

159 

160def test_read_config_filename(): 

161 """ 

162 Test explicit configuration filename. 

163 """ 

164 

165 cfg = pyyc.mod.read_config(pyyc.mod.PYYC_PATH.joinpath("default.cfg")) 

166 assert cfg["DEFAULT"]["version"] == "cfg-1.0" 

167 

168 

169def test_read_config_IOError(): 

170 """ 

171 Test non-existing or invalid configuration files. 

172 """ 

173 

174 with pytest.raises(IOError): 

175 pyyc.mod.read_config("nonexisting.cfg") # Non-existing file 

176 

177 

178def test_format_pkg_tree(): 

179 """ 

180 Test standard usage of :func:`pyyc.mod.format_pkg_tree`. 

181 """ 

182 

183 s = pyyc.mod.format_pkg_tree(pyyc, max_depth=1) 

184 assert s == [ 

185 "pyyc", 

186 " pyyc.config", 

187 " pyyc.mod", 

188 " pyyc.subpkgA", 

189 " pyyc.subpkgB", 

190 ] 

191 

192 

193def test_greetings(capsys, monkeypatch): 

194 """ 

195 This test uses both input monkey patching and stdout capture. 

196 """ 

197 

198 import builtins 

199 

200 # Create a fake 'input' function for the test 

201 monkeypatch.setattr(builtins, "input", lambda _: "John") 

202 

203 pyyc.mod.greetings() # Use fake input, and print on stdout 

204 

205 captured = capsys.readouterr() # Capture standard & error outputs 

206 assert captured.out == "Hello, John!\n"