Coverage for tests / integration / tools / test_sqlfluff_integration.py: 100%
64 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Integration tests for SQLFluff tool definition.
3These tests require sqlfluff to be installed and available in PATH.
4They verify the SqlfluffPlugin definition, check command, fix command,
5and set_options method.
6"""
8from __future__ import annotations
10import shutil
11from collections.abc import Callable
12from pathlib import Path
13from typing import TYPE_CHECKING
15import pytest
16from assertpy import assert_that
18if TYPE_CHECKING:
19 from lintro.plugins.base import BaseToolPlugin
21# Skip all tests if sqlfluff is not installed
22pytestmark = pytest.mark.skipif(
23 shutil.which("sqlfluff") is None,
24 reason="sqlfluff not installed",
25)
28@pytest.fixture
29def temp_sql_file_with_issues(tmp_path: Path) -> str:
30 """Create a temporary SQL file with linting issues.
32 Creates a file containing SQL with deliberate linting issues
33 that sqlfluff should detect, including:
34 - Lowercase keywords
35 - Missing aliases
37 Also creates a .sqlfluff config file with dialect=ansi since
38 SQLFluff v3.0.0+ requires a dialect to be specified.
40 Args:
41 tmp_path: Pytest fixture providing a temporary directory.
43 Returns:
44 Path to the created file as a string.
45 """
46 # Create .sqlfluff config with dialect (required in v3.0.0+)
47 config_path = tmp_path / ".sqlfluff"
48 config_path.write_text(
49 """\
50[sqlfluff]
51dialect = ansi
52""",
53 )
54 file_path = tmp_path / "query.sql"
55 file_path.write_text(
56 """\
57-- SQL file with linting issues
58select id, name from users where id = 1;
59SELECT u.id, u.name FROM users u;
60""",
61 )
62 return str(file_path)
65@pytest.fixture
66def temp_sql_file_clean(tmp_path: Path) -> str:
67 """Create a temporary SQL file with no issues.
69 Creates a file containing properly formatted SQL that should pass
70 sqlfluff checking with minimal issues.
72 Also creates a .sqlfluff config file with dialect=ansi since
73 SQLFluff v3.0.0+ requires a dialect to be specified.
75 Args:
76 tmp_path: Pytest fixture providing a temporary directory.
78 Returns:
79 Path to the created file as a string.
80 """
81 # Create .sqlfluff config with dialect (required in v3.0.0+)
82 config_path = tmp_path / ".sqlfluff"
83 config_path.write_text(
84 """\
85[sqlfluff]
86dialect = ansi
87""",
88 )
89 file_path = tmp_path / "clean.sql"
90 file_path.write_text(
91 """\
92-- Clean SQL file
93SELECT
94 id,
95 name
96FROM users
97WHERE id = 1;
98""",
99 )
100 return str(file_path)
103# --- Tests for SqlfluffPlugin definition ---
106@pytest.mark.parametrize(
107 ("attr", "expected"),
108 [
109 ("name", "sqlfluff"),
110 ("can_fix", True),
111 ],
112 ids=["name", "can_fix"],
113)
114def test_definition_attributes(
115 get_plugin: Callable[[str], BaseToolPlugin],
116 attr: str,
117 expected: object,
118) -> None:
119 """Verify SqlfluffPlugin definition has correct attribute values.
121 Tests that the plugin definition exposes the expected values for
122 name and can_fix attributes.
124 Args:
125 get_plugin: Fixture factory to get plugin instances.
126 attr: The attribute name to check on the definition.
127 expected: The expected value of the attribute.
128 """
129 sqlfluff_plugin = get_plugin("sqlfluff")
130 assert_that(getattr(sqlfluff_plugin.definition, attr)).is_equal_to(expected)
133def test_definition_file_patterns(
134 get_plugin: Callable[[str], BaseToolPlugin],
135) -> None:
136 """Verify SqlfluffPlugin definition includes expected file patterns.
138 Tests that the plugin is configured to handle SQL files.
140 Args:
141 get_plugin: Fixture factory to get plugin instances.
142 """
143 sqlfluff_plugin = get_plugin("sqlfluff")
144 assert_that(sqlfluff_plugin.definition.file_patterns).contains("*.sql")
147def test_definition_tool_type(
148 get_plugin: Callable[[str], BaseToolPlugin],
149) -> None:
150 """Verify SqlfluffPlugin is both a linter and formatter.
152 Args:
153 get_plugin: Fixture factory to get plugin instances.
154 """
155 from lintro.enums.tool_type import ToolType
157 sqlfluff_plugin = get_plugin("sqlfluff")
158 expected_type = ToolType.LINTER | ToolType.FORMATTER
159 assert_that(sqlfluff_plugin.definition.tool_type).is_equal_to(expected_type)
162# --- Integration tests for sqlfluff check command ---
165def test_check_file_with_issues(
166 get_plugin: Callable[[str], BaseToolPlugin],
167 temp_sql_file_with_issues: str,
168) -> None:
169 """Verify sqlfluff check detects linting issues in SQL files.
171 Runs sqlfluff on a file containing deliberate linting issues
172 and verifies that issues are found.
174 Args:
175 get_plugin: Fixture factory to get plugin instances.
176 temp_sql_file_with_issues: Path to file with linting issues.
177 """
178 sqlfluff_plugin = get_plugin("sqlfluff")
179 result = sqlfluff_plugin.check([temp_sql_file_with_issues], {})
181 assert_that(result).is_not_none()
182 assert_that(result.name).is_equal_to("sqlfluff")
183 # SQLFluff should detect at least one issue
184 assert_that(result.issues_count).is_greater_than(0)
185 # success should be False when issues are detected
186 assert_that(result.success).is_false()
189def test_check_clean_file(
190 get_plugin: Callable[[str], BaseToolPlugin],
191 temp_sql_file_clean: str,
192) -> None:
193 """Verify sqlfluff check handles clean files.
195 Runs sqlfluff on a properly formatted file and verifies the result.
197 Args:
198 get_plugin: Fixture factory to get plugin instances.
199 temp_sql_file_clean: Path to file with no issues.
200 """
201 sqlfluff_plugin = get_plugin("sqlfluff")
202 result = sqlfluff_plugin.check([temp_sql_file_clean], {})
204 assert_that(result).is_not_none()
205 assert_that(result.name).is_equal_to("sqlfluff")
206 assert_that(result.success).is_true()
207 assert_that(result.issues_count).is_equal_to(0)
210def test_check_empty_directory(
211 get_plugin: Callable[[str], BaseToolPlugin],
212 tmp_path: Path,
213) -> None:
214 """Verify sqlfluff check handles empty directories gracefully.
216 Runs sqlfluff on an empty directory and verifies a result is returned
217 without errors.
219 Args:
220 get_plugin: Fixture factory to get plugin instances.
221 tmp_path: Pytest fixture providing a temporary directory.
222 """
223 sqlfluff_plugin = get_plugin("sqlfluff")
224 result = sqlfluff_plugin.check([str(tmp_path)], {})
226 assert_that(result).is_not_none()
229# --- Integration tests for sqlfluff fix command ---
232def test_fix_formats_sql_file(
233 get_plugin: Callable[[str], BaseToolPlugin],
234 temp_sql_file_with_issues: str,
235) -> None:
236 """Verify sqlfluff fix formats SQL files.
238 Runs sqlfluff fix on a file with linting issues and verifies
239 that the operation completes successfully.
241 Args:
242 get_plugin: Fixture factory to get plugin instances.
243 temp_sql_file_with_issues: Path to file with linting issues.
244 """
245 sqlfluff_plugin = get_plugin("sqlfluff")
246 result = sqlfluff_plugin.fix([temp_sql_file_with_issues], {})
248 assert_that(result).is_not_none()
249 assert_that(result.name).is_equal_to("sqlfluff")
250 assert_that(result.success).is_true()
251 assert_that(result.issues_count).is_equal_to(0)
254# --- Tests for SqlfluffPlugin.set_options method ---
257@pytest.mark.parametrize(
258 ("option_name", "option_value"),
259 [
260 ("dialect", "ansi"),
261 ("dialect", "postgres"),
262 ("dialect", "mysql"),
263 ("templater", "raw"),
264 ("templater", "jinja"),
265 ("exclude_rules", ["L010", "L014"]),
266 ("rules", ["L001", "L002"]),
267 ],
268 ids=[
269 "dialect_ansi",
270 "dialect_postgres",
271 "dialect_mysql",
272 "templater_raw",
273 "templater_jinja",
274 "exclude_rules",
275 "rules",
276 ],
277)
278def test_set_options(
279 get_plugin: Callable[[str], BaseToolPlugin],
280 option_name: str,
281 option_value: object,
282) -> None:
283 """Verify SqlfluffPlugin.set_options correctly sets various options.
285 Tests that plugin options can be set and retrieved correctly.
287 Args:
288 get_plugin: Fixture factory to get plugin instances.
289 option_name: Name of the option to set.
290 option_value: Value to set for the option.
291 """
292 sqlfluff_plugin = get_plugin("sqlfluff")
293 sqlfluff_plugin.set_options(**{option_name: option_value})
294 assert_that(sqlfluff_plugin.options.get(option_name)).is_equal_to(option_value)