Skip to content

Commit 713037d

Browse files
Merge pull request #38 from open-pomodoro/add-blackbox-tests
Add comprehensive BATS black box testing framework
2 parents 31ac7ab + c436128 commit 713037d

File tree

17 files changed

+692
-11
lines changed

17 files changed

+692
-11
lines changed

.github/workflows/test.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
matrix:
14+
os: [ubuntu-latest, macos-latest]
15+
go-version: [1.21]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: ${{ matrix.go-version }}
24+
25+
- name: Run tests
26+
run: make test

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
dist/
2+
.bats/
3+
pomodoro

Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
BATS_VERSION := v1.11.0
2+
BATS_DIR := .bats
3+
BATS := $(BATS_DIR)/bin/bats
4+
BINARY := pomodoro
5+
6+
GO_SOURCES := $(shell find . -name '*.go' -not -path './vendor/*')
7+
8+
.PHONY: test
9+
test: $(BINARY) $(BATS)
10+
$(BATS) test/
11+
12+
$(BINARY): $(GO_SOURCES) go.mod go.sum
13+
go build -o $(BINARY) .
14+
15+
$(BATS):
16+
@mkdir -p $(BATS_DIR)
17+
@echo "Downloading bats-core $(BATS_VERSION)..."
18+
@curl -sSL https://github.com/bats-core/bats-core/archive/$(BATS_VERSION).tar.gz | tar xz -C $(BATS_DIR) --strip-components=1
19+
@chmod +x $(BATS_DIR)/bin/bats
20+
21+
.PHONY: clean
22+
clean:
23+
rm -rf $(BATS_DIR) $(BINARY)

cmd/root.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,18 @@ func init() {
4444

4545
viper.AutomaticEnv()
4646

47-
var err error
47+
RootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {
48+
var err error
4849

49-
client, err = openpomodoro.NewClient(directoryFlag)
50-
if err != nil {
51-
log.Fatalf("Could not create client: %v", err)
52-
}
50+
client, err = openpomodoro.NewClient(directoryFlag)
51+
if err != nil {
52+
log.Fatalf("Could not create client: %v", err)
53+
}
5354

54-
settings, err = client.Settings()
55-
if err != nil {
56-
log.Fatalf("Could not retrieve settings: %v", err)
55+
settings, err = client.Settings()
56+
if err != nil {
57+
log.Fatalf("Could not retrieve settings: %v", err)
58+
}
5759
}
5860
}
5961

cmd/start.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ func init() {
2727
"time ago this Pomodoro started")
2828

2929
command.Flags().IntVarP(
30-
&durationFlag, "duration", "d",
31-
int(settings.DefaultPomodoroDuration.Minutes()),
30+
&durationFlag, "duration", "d", 0,
3231
"duration for this Pomodoro")
3332

3433
command.Flags().StringArrayVarP(
@@ -43,7 +42,11 @@ func startCmd(cmd *cobra.Command, args []string) error {
4342

4443
p := openpomodoro.NewPomodoro()
4544
p.Description = description
46-
p.Duration = time.Duration(durationFlag) * time.Minute
45+
if durationFlag == 0 {
46+
p.Duration = settings.DefaultPomodoroDuration
47+
} else {
48+
p.Duration = time.Duration(durationFlag) * time.Minute
49+
}
4750
p.StartTime = time.Now().Add(-agoFlag)
4851
p.Tags = tagsFlag
4952

test/amend.bats

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "amend changes description of current pomodoro" {
6+
pomodoro start "Original task"
7+
run pomodoro amend "Amended task"
8+
[ "$status" -eq 0 ]
9+
assert_file_contains "current" "Amended task"
10+
}
11+
12+
@test "amend adds tags to current pomodoro" {
13+
pomodoro start "Task"
14+
run pomodoro amend -t "work,urgent"
15+
[ "$status" -eq 0 ]
16+
assert_file_contains "current" "tags=work,urgent"
17+
}
18+
19+
@test "amend changes duration of current pomodoro" {
20+
pomodoro start "Task"
21+
run pomodoro amend -d 45
22+
[ "$status" -eq 0 ]
23+
assert_file_contains "current" "duration=45"
24+
}
25+
26+
27+
@test "amend creates new current when no current exists" {
28+
pomodoro start "Task" --ago 5m
29+
pomodoro finish
30+
run pomodoro amend "New task"
31+
[ "$status" -eq 0 ]
32+
assert_file_contains "current" "New task"
33+
}
34+
35+
@test "amend outputs current pomodoro status" {
36+
pomodoro start "Task"
37+
run pomodoro amend "Amended task"
38+
[ "$status" -eq 0 ]
39+
[[ "$output" =~ "Amended task" ]]
40+
}
41+
42+
@test "amend with no arguments succeeds" {
43+
pomodoro start "Task"
44+
run pomodoro amend
45+
[ "$status" -eq 0 ]
46+
assert_file_contains "current" "Task"
47+
}

test/break.bats

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "break executes break hook before starting timer" {
6+
create_hook "break" 'echo "BREAK_HOOK" >> "$TEST_DIR/hook_log"; exit 1'
7+
8+
run pomodoro break
9+
[ "$status" -ne 0 ]
10+
11+
assert_hook_contains "BREAK_HOOK"
12+
}
13+
14+
@test "break with custom duration parses correctly" {
15+
create_hook "break" 'echo "BREAK_STARTED" >> "$TEST_DIR/hook_log"; exit 1'
16+
17+
run pomodoro break "10"
18+
[ "$status" -ne 0 ]
19+
20+
assert_hook_contains "BREAK_STARTED"
21+
}
22+
23+
@test "break with invalid duration fails" {
24+
run pomodoro break "invalid"
25+
[ "$status" -ne 0 ]
26+
}

test/cancel.bats

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "cancel empties current file and removes from history" {
6+
pomodoro start "Task to cancel"
7+
run pomodoro cancel
8+
[ "$status" -eq 0 ]
9+
assert_file_empty "current"
10+
assert_file_empty "history"
11+
}
12+
13+
@test "cancel preserves existing history but removes current" {
14+
pomodoro start "First task" --ago 5m
15+
pomodoro finish
16+
pomodoro start "Task to cancel"
17+
run pomodoro cancel
18+
[ "$status" -eq 0 ]
19+
20+
assert_file_contains "history" "First task"
21+
assert_file_empty "current"
22+
}
23+
24+
@test "cancel with no current pomodoro succeeds" {
25+
run pomodoro cancel
26+
[ "$status" -eq 0 ]
27+
assert_file_empty "current"
28+
}
29+
30+
@test "cancel produces no output" {
31+
pomodoro start "Test task"
32+
run pomodoro cancel
33+
[ "$status" -eq 0 ]
34+
[ -z "$output" ]
35+
}

test/clear.bats

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "clear empties current file and does not affect history" {
6+
pomodoro start "First task" --ago 5m
7+
pomodoro finish
8+
pomodoro start "Second task"
9+
run pomodoro clear
10+
[ "$status" -eq 0 ]
11+
12+
assert_file_contains "history" "First task"
13+
assert_file_empty "current"
14+
}
15+
16+
@test "clear with no current pomodoro succeeds" {
17+
run pomodoro clear
18+
[ "$status" -eq 0 ]
19+
assert_file_empty "current"
20+
}
21+
22+
@test "clear produces no output" {
23+
pomodoro start "Test task"
24+
run pomodoro clear
25+
[ "$status" -eq 0 ]
26+
[ -z "$output" ]
27+
}

test/finish.bats

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "finish moves current pomodoro to history" {
6+
pomodoro start "Work session"
7+
run pomodoro finish
8+
[ "$status" -eq 0 ]
9+
10+
assert_file_empty "current"
11+
assert_file_contains "history" "Work session"
12+
}
13+
14+
@test "finish records actual elapsed time in history" {
15+
pomodoro start "Work session" -d 30 --ago 10m
16+
run pomodoro finish
17+
[ "$status" -eq 0 ]
18+
19+
assert_file_contains "history" "Work session"
20+
assert_file_contains "history" "duration=10"
21+
}
22+
23+
@test "finish appends to existing history" {
24+
pomodoro start "First task" --ago 5m
25+
pomodoro finish
26+
pomodoro start "Second task" --ago 3m
27+
run pomodoro finish
28+
[ "$status" -eq 0 ]
29+
30+
assert_file_contains "history" "First task"
31+
assert_file_contains "history" "Second task"
32+
}
33+
34+
@test "finish outputs elapsed time" {
35+
pomodoro start "Test task" --ago 5m
36+
run pomodoro finish
37+
[ "$status" -eq 0 ]
38+
[[ "$output" =~ "5:" ]]
39+
}
40+
41+
@test "finish with no current pomodoro succeeds" {
42+
run pomodoro finish
43+
[ "$status" -eq 0 ]
44+
assert_file_empty "current"
45+
}

0 commit comments

Comments
 (0)