300
.tests/unit/test_parsers.py
Normal file
300
.tests/unit/test_parsers.py
Normal file
@@ -0,0 +1,300 @@
|
||||
"""Unit tests for parsers."""
|
||||
|
||||
import pytest
|
||||
import os
|
||||
from code_doc_cli.parsers.python_parser import PythonParser
|
||||
from code_doc_cli.parsers.typescript_parser import TypeScriptParser
|
||||
from code_doc_cli.parsers.go_parser import GoParser
|
||||
from code_doc_cli.parsers.registry import ParserRegistry
|
||||
from code_doc_cli.parsers.base import ElementType
|
||||
import tempfile
|
||||
|
||||
|
||||
class TestPythonParser:
|
||||
"""Tests for Python parser."""
|
||||
|
||||
def test_parse_function(self):
|
||||
"""Test parsing a Python function."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
||||
f.write('''
|
||||
def add(a: int, b: int) -> int:
|
||||
"""Add two numbers together.
|
||||
|
||||
Args:
|
||||
a: First number
|
||||
b: Second number
|
||||
|
||||
Returns:
|
||||
The sum of a and b
|
||||
"""
|
||||
return a + b
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = PythonParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
assert len(elements) > 0
|
||||
|
||||
func_names = [e.name for e in elements]
|
||||
assert "add" in func_names
|
||||
|
||||
add_elem = next(e for e in elements if e.name == "add")
|
||||
assert add_elem.element_type == ElementType.FUNCTION
|
||||
assert len(add_elem.parameters) == 2
|
||||
|
||||
def test_parse_class(self):
|
||||
"""Test parsing a Python class."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
||||
f.write('''
|
||||
class Calculator:
|
||||
"""A simple calculator class."""
|
||||
|
||||
def __init__(self, initial: int = 0):
|
||||
"""Initialize calculator."""
|
||||
self.memory = initial
|
||||
|
||||
def multiply(self, x: int, y: int) -> int:
|
||||
"""Multiply two numbers."""
|
||||
return x * y
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = PythonParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
class_names = [e.name for e in elements]
|
||||
assert "Calculator" in class_names
|
||||
|
||||
calc_elem = next(e for e in elements if e.name == "Calculator")
|
||||
assert calc_elem.element_type == ElementType.CLASS
|
||||
|
||||
def test_parse_module(self):
|
||||
"""Test parsing module docstring."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
||||
f.write('''"""This is a test module."""
|
||||
|
||||
def test_func():
|
||||
pass
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = PythonParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
module_elems = [e for e in elements if e.element_type == ElementType.MODULE]
|
||||
assert len(module_elems) == 1
|
||||
assert "test module" in module_elems[0].description.lower()
|
||||
|
||||
def test_language_name(self):
|
||||
"""Test language name detection."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
|
||||
f.write("x = 1\n")
|
||||
f.flush()
|
||||
|
||||
parser = PythonParser(f.name)
|
||||
os.unlink(f.name)
|
||||
|
||||
assert parser.get_language_name() == "python"
|
||||
|
||||
def test_supports_file(self):
|
||||
"""Test file extension support."""
|
||||
assert PythonParser.supports_file("test.py")
|
||||
assert PythonParser.supports_file("test.pyw")
|
||||
assert not PythonParser.supports_file("test.ts")
|
||||
assert not PythonParser.supports_file("test.go")
|
||||
|
||||
|
||||
class TestTypeScriptParser:
|
||||
"""Tests for TypeScript parser."""
|
||||
|
||||
def test_parse_function(self):
|
||||
"""Test parsing a TypeScript function."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".ts", delete=False) as f:
|
||||
f.write('''
|
||||
export function add(a: number, b: number): number {
|
||||
return a + b;
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = TypeScriptParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
func_names = [e.name for e in elements if e.element_type == ElementType.FUNCTION]
|
||||
assert "add" in func_names
|
||||
|
||||
def test_parse_interface(self):
|
||||
"""Test parsing a TypeScript interface."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".ts", delete=False) as f:
|
||||
f.write('''
|
||||
export interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = TypeScriptParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
interface_names = [e.name for e in elements if e.element_type == ElementType.INTERFACE]
|
||||
assert "User" in interface_names
|
||||
|
||||
def test_parse_class(self):
|
||||
"""Test parsing a TypeScript class."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".ts", delete=False) as f:
|
||||
f.write('''
|
||||
export class Calculator {
|
||||
private memory: number;
|
||||
|
||||
constructor(initial: number = 0) {
|
||||
this.memory = initial;
|
||||
}
|
||||
|
||||
public multiply(x: number, y: number): number {
|
||||
return x * y;
|
||||
}
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = TypeScriptParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
class_names = [e.name for e in elements if e.element_type == ElementType.CLASS]
|
||||
assert "Calculator" in class_names
|
||||
|
||||
def test_language_name(self):
|
||||
"""Test language name detection."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".ts", delete=False) as f:
|
||||
f.write("const x = 1;\n")
|
||||
f.flush()
|
||||
|
||||
parser = TypeScriptParser(f.name)
|
||||
os.unlink(f.name)
|
||||
|
||||
assert parser.get_language_name() == "typescript"
|
||||
|
||||
def test_supports_file(self):
|
||||
"""Test file extension support."""
|
||||
assert TypeScriptParser.supports_file("test.ts")
|
||||
assert TypeScriptParser.supports_file("test.tsx")
|
||||
assert not TypeScriptParser.supports_file("test.py")
|
||||
|
||||
|
||||
class TestGoParser:
|
||||
"""Tests for Go parser."""
|
||||
|
||||
def test_parse_function(self):
|
||||
"""Test parsing a Go function."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".go", delete=False) as f:
|
||||
f.write('''
|
||||
package main
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = GoParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
func_names = [e.name for e in elements if e.element_type == ElementType.FUNCTION]
|
||||
assert "Add" in func_names
|
||||
|
||||
def test_parse_struct(self):
|
||||
"""Test parsing a Go struct."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".go", delete=False) as f:
|
||||
f.write('''
|
||||
package main
|
||||
|
||||
type Calculator struct {
|
||||
memory int
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = GoParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
struct_names = [e.name for e in elements if e.element_type == ElementType.STRUCT]
|
||||
assert "Calculator" in struct_names
|
||||
|
||||
def test_parse_package(self):
|
||||
"""Test parsing package docstring."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".go", delete=False) as f:
|
||||
f.write('''// Package main provides math functions.
|
||||
package main
|
||||
|
||||
func Add(a, b int) int {
|
||||
return a + b
|
||||
}
|
||||
''')
|
||||
f.flush()
|
||||
|
||||
parser = GoParser(f.name)
|
||||
elements = parser.parse()
|
||||
|
||||
os.unlink(f.name)
|
||||
|
||||
module_elems = [e for e in elements if e.element_type == ElementType.MODULE]
|
||||
assert len(module_elems) >= 1
|
||||
|
||||
def test_language_name(self):
|
||||
"""Test language name detection."""
|
||||
with tempfile.NamedTemporaryFile(mode="w", suffix=".go", delete=False) as f:
|
||||
f.write("package main\n")
|
||||
f.flush()
|
||||
|
||||
parser = GoParser(f.name)
|
||||
os.unlink(f.name)
|
||||
|
||||
assert parser.get_language_name() == "go"
|
||||
|
||||
def test_supports_file(self):
|
||||
"""Test file extension support."""
|
||||
assert GoParser.supports_file("test.go")
|
||||
assert not GoParser.supports_file("test.py")
|
||||
|
||||
|
||||
class TestParserRegistry:
|
||||
"""Tests for parser registry."""
|
||||
|
||||
def test_get_parser_class(self):
|
||||
"""Test getting parser class by language."""
|
||||
assert ParserRegistry.get_parser_class("python") == PythonParser
|
||||
assert ParserRegistry.get_parser_class("py") == PythonParser
|
||||
assert ParserRegistry.get_parser_class("typescript") == TypeScriptParser
|
||||
assert ParserRegistry.get_parser_class("ts") == TypeScriptParser
|
||||
assert ParserRegistry.get_parser_class("go") == GoParser
|
||||
|
||||
def test_get_language_from_extension(self):
|
||||
"""Test language detection from extension."""
|
||||
assert ParserRegistry.get_language_from_extension("test.py") == "python"
|
||||
assert ParserRegistry.get_language_from_extension("test.ts") == "typescript"
|
||||
assert ParserRegistry.get_language_from_extension("test.go") == "go"
|
||||
|
||||
def test_get_supported_languages(self):
|
||||
"""Test getting supported languages."""
|
||||
languages = ParserRegistry.get_supported_languages()
|
||||
assert "python" in languages
|
||||
assert "typescript" in languages
|
||||
assert "go" in languages
|
||||
Reference in New Issue
Block a user