aboutsummaryrefslogtreecommitdiff
path: root/tests/Makefile
blob: 12e81f195192aa7824ba6c94767ef9bb8e4748b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# Makefile for chime.el test suite
# Usage:
#   make test              - Run all tests
#   make test-file FILE=overdue - Run tests in one file
#   make test-one TEST=name     - Run one specific test
#   make test-unit         - Run unit tests only
#   make test-integration  - Run integration tests only
#   make clean             - Remove byte-compiled files

# Configuration
EMACS ?= emacs
EMACSFLAGS = --batch -Q
TESTFLAGS = -l ert

# Dependency paths (adjust if needed)
ELPA_DIR = $(HOME)/.emacs.d/elpa
DASH_DIR = $(shell find $(ELPA_DIR) -maxdepth 1 -name 'dash-*' -type d 2>/dev/null | head -1)
ALERT_DIR = $(shell find $(ELPA_DIR) -maxdepth 1 -name 'alert-*' -type d 2>/dev/null | head -1)
ASYNC_DIR = $(shell find $(ELPA_DIR) -maxdepth 1 -name 'async-*' -type d 2>/dev/null | head -1)

# Build load path
LOADPATH = -L $(DASH_DIR) -L $(ALERT_DIR) -L $(ASYNC_DIR)

# Test files
ALL_TESTS = $(filter-out test-bootstrap.el,$(wildcard test-*.el))
UNIT_TESTS = $(filter-out test-integration-%.el,$(ALL_TESTS))
INTEGRATION_TESTS = $(wildcard test-integration-*.el)

# Colors for output (if terminal supports it)
RED = \033[0;31m
GREEN = \033[0;32m
YELLOW = \033[1;33m
NC = \033[0m # No Color

.PHONY: all test test-file test-one test-name test-unit test-integration validate lint clean help check-deps

# Default target
all: test

# Check if dependencies are available
check-deps:
	@if [ -z "$(DASH_DIR)" ]; then \
		echo "$(RED)Error: dash package not found in $(ELPA_DIR)$(NC)"; \
		exit 1; \
	fi
	@if [ -z "$(ALERT_DIR)" ]; then \
		echo "$(RED)Error: alert package not found in $(ELPA_DIR)$(NC)"; \
		exit 1; \
	fi
	@if [ -z "$(ASYNC_DIR)" ]; then \
		echo "$(RED)Error: async package not found in $(ELPA_DIR)$(NC)"; \
		exit 1; \
	fi
	@echo "$(GREEN)✓ All dependencies found$(NC)"

# Run all tests
test: check-deps
	@echo "$(YELLOW)Running all tests ($(words $(ALL_TESTS)) files)...$(NC)"
	@$(MAKE) --no-print-directory test-unit
	@$(MAKE) --no-print-directory test-integration
	@echo "$(GREEN)[✓] All tests complete$(NC)"

# Run tests in one file
test-file: check-deps
ifndef FILE
	@echo "$(RED)Error: FILE not specified$(NC)"
	@echo "Usage: make test-file FILE=overdue"
	@echo "       make test-file FILE=test-chime-overdue-todos.el"
	@exit 1
endif
	@TESTFILE=$$(find . -maxdepth 1 -name "*$(FILE)*.el" -type f | head -1); \
	if [ -z "$$TESTFILE" ]; then \
		echo "$(RED)Error: No test file matching '$(FILE)' found$(NC)"; \
		exit 1; \
	fi; \
	echo "$(YELLOW)Running tests in $$TESTFILE...$(NC)"; \
	$(EMACS) $(EMACSFLAGS) $(LOADPATH) $(TESTFLAGS) -l "$$TESTFILE" \
		--eval '(ert-run-tests-batch-and-exit)' 2>&1 | tee test-file-output.log; \
	if [ $$? -eq 0 ]; then \
		echo "$(GREEN)✓ All tests in $$TESTFILE passed!$(NC)"; \
	else \
		echo "$(RED)✗ Some tests failed.$(NC)"; \
		exit 1; \
	fi

# Run one specific test
test-one: check-deps
ifndef TEST
	@echo "$(RED)Error: TEST not specified$(NC)"
	@echo "Usage: make test-one TEST=pilot"
	@echo "       make test-one TEST=test-overdue-has-passed-time-today-all-day"
	@exit 1
endif
	@echo "$(YELLOW)Searching for test matching '$(TEST)'...$(NC)"
	@TESTFILE=$$(grep -l "ert-deftest.*$(TEST)" test-*.el 2>/dev/null | head -1); \
	if [ -z "$$TESTFILE" ]; then \
		echo "$(RED)Error: No test matching '$(TEST)' found$(NC)"; \
		exit 1; \
	fi; \
	TESTNAME=$$(grep "ert-deftest.*$(TEST)" "$$TESTFILE" | sed 's/^(ert-deftest \([^ ]*\).*/\1/' | head -1); \
	echo "$(YELLOW)Running test '$$TESTNAME' in $$TESTFILE...$(NC)"; \
	$(EMACS) $(EMACSFLAGS) $(LOADPATH) $(TESTFLAGS) -l "$$TESTFILE" \
		--eval "(ert-run-tests-batch-and-exit \"$$TESTNAME\")" 2>&1; \
	if [ $$? -eq 0 ]; then \
		echo "$(GREEN)✓ Test $$TESTNAME passed!$(NC)"; \
	else \
		echo "$(RED)✗ Test $$TESTNAME failed.$(NC)"; \
		exit 1; \
	fi

# Run only unit tests
test-unit: check-deps
	@echo "$(YELLOW)Running unit tests ($(words $(UNIT_TESTS)) files)...$(NC)"
	@failed=0; \
	for testfile in $(UNIT_TESTS); do \
		echo "  Testing $$testfile..."; \
		$(EMACS) $(EMACSFLAGS) $(LOADPATH) $(TESTFLAGS) -l "$$testfile" \
			--eval '(ert-run-tests-batch-and-exit)' || failed=$$((failed + 1)); \
	done; \
	if [ $$failed -eq 0 ]; then \
		echo "$(GREEN)[✓] All unit tests passed$(NC)"; \
	else \
		echo "$(RED)[✗] $$failed unit test file(s) failed$(NC)"; \
		exit 1; \
	fi

# Run only integration tests
test-integration: check-deps
	@echo "$(YELLOW)Running integration tests ($(words $(INTEGRATION_TESTS)) files)...$(NC)"
	@failed=0; \
	for testfile in $(INTEGRATION_TESTS); do \
		echo "  Testing $$testfile..."; \
		$(EMACS) $(EMACSFLAGS) $(LOADPATH) $(TESTFLAGS) -l "$$testfile" \
			--eval '(ert-run-tests-batch-and-exit)' || failed=$$((failed + 1)); \
	done; \
	if [ $$failed -eq 0 ]; then \
		echo "$(GREEN)[✓] All integration tests passed$(NC)"; \
	else \
		echo "$(RED)[✗] $$failed integration test file(s) failed$(NC)"; \
		exit 1; \
	fi

# Run tests matching a name pattern (ERT selector)
test-name: check-deps
ifndef TEST
	@echo "$(RED)Error: TEST not specified$(NC)"
	@echo "Usage: make test-name TEST=test-chime-check-early-return"
	@echo "       make test-name TEST='test-chime-check-*'"
	@exit 1
endif
	@echo "$(YELLOW)Running tests matching pattern: $(TEST)...$(NC)"
	@$(EMACS) $(EMACSFLAGS) $(LOADPATH) $(TESTFLAGS) \
		--eval "(dolist (f (directory-files \".\" t \"^test-.*\\\\.el$$\")) (load f))" \
		--eval '(ert-run-tests-batch-and-exit "$(TEST)")'

# Count tests
count:
	@echo "Test file inventory:"
	@for f in $(ALL_TESTS); do \
		count=$$(grep -c "^(ert-deftest" "$$f" 2>/dev/null || echo 0); \
		printf "%3d tests - %s\n" "$$count" "$$f"; \
	done | sort -rn
	@total=$$(find . -name "test-*.el" -exec grep -c "^(ert-deftest" {} \; | awk '{sum+=$$1} END {print sum}'); \
	echo "$(GREEN)Total: $$total tests across $(words $(ALL_TESTS)) files$(NC)"

# List all available tests
list:
	@echo "Available tests:"
	@grep -h "^(ert-deftest" test-*.el | sed 's/^(ert-deftest \([^ ]*\).*/  \1/' | sort

# Validate Emacs Lisp syntax
validate:
	@echo "$(YELLOW)Validating Emacs Lisp syntax...$(NC)"
	@failed=0; \
	total=0; \
	for file in ../chime.el test-*.el testutil-*.el; do \
		if [ -f "$$file" ] && [ ! -d "$$file" ]; then \
			total=$$((total + 1)); \
			output=$$($(EMACS) --batch $(LOADPATH) --eval "(progn \
				(setq byte-compile-error-on-warn nil) \
				(find-file \"$$file\") \
				(condition-case err \
					(progn \
						(check-parens) \
						(message \"✓ $$file - parentheses balanced\")) \
					(error \
						(message \"✗ $$file: %s\" (error-message-string err)) \
						(kill-emacs 1))))" 2>&1 | grep -E '(✓|✗)'); \
			if [ $$? -eq 0 ]; then \
				echo "$(GREEN)$$output$(NC)"; \
			else \
				echo "$(RED)$$output$(NC)"; \
				failed=$$((failed + 1)); \
			fi; \
		fi; \
	done; \
	if [ $$failed -eq 0 ]; then \
		echo "$(GREEN)✓ All $$total files validated successfully$(NC)"; \
	else \
		echo "$(RED)✗ $$failed of $$total files failed validation$(NC)"; \
		exit 1; \
	fi

# Comprehensive linting with elisp-lint
lint:
	@echo "$(YELLOW)Running elisp-lint...$(NC)"
	@$(EMACS) --batch --eval "(progn \
		(require 'package) \
		(package-initialize) \
		(require 'elisp-lint))" \
		-f elisp-lint-files-batch \
		--no-checkdoc \
		../chime.el test-*.el testutil-*.el 2>&1; \
	if [ $$? -eq 0 ]; then \
		echo "$(GREEN)✓ Linting completed successfully$(NC)"; \
	else \
		echo "$(RED)✗ Linting found issues (see above)$(NC)"; \
		exit 1; \
	fi

# Clean byte-compiled files
clean:
	@echo "$(YELLOW)Cleaning byte-compiled files...$(NC)"
	@rm -f *.elc ../*.elc
	@rm -f test-output.log test-file-output.log test-unit-output.log test-integration-output.log
	@echo "$(GREEN)✓ Cleaned$(NC)"

# Show help
help:
	@echo "Chime Test Suite Makefile"
	@echo ""
	@echo "Usage:"
	@echo "  make test                      - Run all tests (unit + integration)"
	@echo "  make test-unit                 - Run unit tests only"
	@echo "  make test-integration          - Run integration tests only"
	@echo "  make test-file FILE=overdue    - Run tests in one file (fuzzy match)"
	@echo "  make test-one TEST=pilot       - Run one specific test (fuzzy match)"
	@echo "  make test-name TEST=pattern    - Run tests matching ERT name pattern"
	@echo "  make validate                  - Validate Emacs Lisp syntax (parens balance)"
	@echo "  make lint                      - Comprehensive linting with elisp-lint"
	@echo "  make count                     - Count tests per file"
	@echo "  make list                      - List all test names"
	@echo "  make clean                     - Remove byte-compiled files and logs"
	@echo "  make check-deps                - Verify all dependencies are installed"
	@echo "  make help                      - Show this help message"
	@echo ""
	@echo "Examples:"
	@echo "  make test                                    # Run everything"
	@echo "  make test-file FILE=overdue                  # Run test-chime-overdue-todos.el"
	@echo "  make test-one TEST=pilot                     # Run the pilot test"
	@echo "  make test-name TEST='test-chime-check-*'     # Run tests matching pattern"
	@echo ""
	@echo "Environment variables:"
	@echo "  EMACS      - Emacs executable (default: emacs)"
	@echo "  ELPA_DIR   - ELPA package directory (default: ~/.emacs.d/elpa)"