Skip to content

Commit d12e76f

Browse files
authored
Increase coverage to 100% (#48)
Fix a discovered bug too.
1 parent 0cc1969 commit d12e76f

3 files changed

Lines changed: 67 additions & 15 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ To test:
7878
pytest
7979
```
8080

81+
Generate a coverage report with:
82+
83+
```
84+
pytest --cov-report term-missing --cov yaml2ics
85+
```
86+
8187
[black](https://github.com/psf/black) and other linters are used to auto-format
8288
files (and enforced by CI). To install the git hooks, use `pre-commit install`.
8389
To run the tests/auto-formatting manually, use `pre-commit run --all-files`.

tests/test_cli.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import os
2+
import sys
3+
4+
import pytest
5+
6+
from yaml2ics import event_from_yaml, main
7+
8+
basedir = os.path.abspath(os.path.join(os.path.dirname(__file__)))
9+
example_calendar = os.path.join(basedir, "../example/test_calendar.yaml")
10+
11+
12+
def test_cli(monkeypatch):
13+
with monkeypatch.context() as m:
14+
m.setattr(sys, "argv", ["yaml2ics.py", example_calendar])
15+
main()
16+
17+
with monkeypatch.context() as m:
18+
m.setattr(sys, "argv", ["yaml2ics.py"])
19+
20+
with pytest.raises(RuntimeError) as e:
21+
main()
22+
assert "Usage:" in str(e)
23+
24+
with monkeypatch.context() as m:
25+
m.setattr(sys, "argv", ["yaml2ics.py", "syzygy.yaml"])
26+
27+
with pytest.raises(RuntimeError) as e:
28+
main()
29+
assert "is not a file" in str(e)
30+
31+
32+
def test_errors():
33+
with pytest.raises(RuntimeError) as e:
34+
event_from_yaml({"repeat": {"interval": {}}})
35+
assert "interval must specify" in str(e)
36+
37+
with pytest.raises(RuntimeError) as e:
38+
event_from_yaml({"ics": "123"})
39+
assert "Invalid custom ICS" in str(e)
40+
41+
with pytest.raises(RuntimeError) as e:
42+
event_from_yaml({"repeat": {"interval": {"weeks": 1}}})
43+
assert "must specify end date for repeating events" in str(e)
44+
45+
with pytest.raises(RuntimeError) as e:
46+
event_from_yaml({"repeat": {"interval": {"epochs": 4}}})
47+
assert "expected interval to be specified in seconds, minutes" in str(e)

yaml2ics.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -75,25 +75,20 @@ def event_from_yaml(event_yaml: dict, tz: datetime.tzinfo = None) -> ics.Event:
7575
interval = repeat["interval"]
7676

7777
if not len(interval) == 1:
78-
print(
78+
raise RuntimeError(
7979
"Error: interval must specify seconds, minutes, hours, days, "
80-
"weeks, months, or years only",
81-
file=sys.stderr,
80+
"weeks, months, or years only"
8281
)
83-
sys.exit(-1)
8482

8583
interval_measure = list(interval.keys())[0]
8684
if interval_measure not in interval_type:
87-
print(
85+
raise RuntimeError(
8886
"Error: expected interval to be specified in seconds, minutes, "
8987
"hours, days, weeks, months, or years only",
90-
file=sys.stderr,
9188
)
92-
sys.exit(-1)
9389

9490
if "until" not in repeat:
95-
print("Error: must specify end date for repeating events", file=sys.stderr)
96-
sys.exit(-1)
91+
raise RuntimeError("Error: must specify end date for " "repeating events")
9792

9893
# This causes zero-length events, I guess overriding whatever duration
9994
# might have been specified
@@ -131,6 +126,8 @@ def event_from_yaml(event_yaml: dict, tz: datetime.tzinfo = None) -> ics.Event:
131126

132127
if ics_custom:
133128
for line in ics_custom.split("\n"):
129+
if not line:
130+
continue
134131
if ":" not in line:
135132
raise RuntimeError(
136133
f"Invalid custom ICS (expected `fieldname:value`):\n {line}"
@@ -191,19 +188,21 @@ def files_to_calendar(files: list) -> ics.Calendar:
191188

192189
def main():
193190
if len(sys.argv) < 2:
194-
print("Usage: yaml2ics.py FILE1.yaml FILE2.yaml ...")
195-
sys.exit(-1)
191+
raise RuntimeError("Usage: yaml2ics.py FILE1.yaml FILE2.yaml ...")
196192

197193
files = sys.argv[1:]
198194
for f in files:
199195
if not os.path.isfile(f):
200-
print(f"Error: {f} is not a file", file=sys.stderr)
201-
sys.exit(-1)
196+
raise RuntimeError(f"Error: {f} is not a file")
202197

203198
calendar = files_to_calendar(files)
204199

205200
print(calendar.serialize())
206201

207202

208-
if __name__ == "__main__":
209-
main()
203+
if __name__ == "__main__": # pragma: no cover
204+
try:
205+
main()
206+
except Exception as e:
207+
print(e, file=sys.stderr)
208+
sys.exit(-1)

0 commit comments

Comments
 (0)