首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Python中隔离ANTLR解析器的测试用例?

如何在Python中隔离ANTLR解析器的测试用例?
EN

Stack Overflow用户
提问于 2021-03-16 20:02:32
回答 1查看 87关注 0票数 1

我想使用Python和ANTLR v4运行时通过一些测试用例来测试我的antlr解析器。我遇到的问题是关于测试用例的隔离。在每个测试用例中,都应该解析另一个文件。但是解析器(或者流阅读器--我不知道)似乎连接了到目前为止读取的文件。因此,在测试用例n中,解析结果是case n-1和case n的结果的连接(并递归返回到第一个测试用例)。

下面是一个最小的工作示例:

文件Minimal.g4

代码语言:javascript
运行
复制
grammar Minimal ;

WS : [ \t\n\r\f] ;

WORD : (~ ([ \n\r\t\f]) )+ ;

text : ( token | WS+ )* ;

token : WORD ;

文件minimal/minimal.py

代码语言:javascript
运行
复制
from antlr4 import *
from minimal.MinimalListener import MinimalListener

class MinimalListListener(MinimalListener):

    tokens = []

    def exitToken(self, ctx):
        self.tokens.append(ctx.WORD().getText())

文件test_minimal.py

代码语言:javascript
运行
复制
import unittest
import os
from antlr4 import *
from minimal.MinimalListener import MinimalListener
from minimal.MinimalLexer import MinimalLexer
from minimal.MinimalParser import MinimalParser

from minimal.minimal import MinimalListListener


class MinimalTstBase(unittest.TestCase):

    fname = None
    
    def setUp(self):
        self.parsed = []
        input_stream = FileStream(os.path.join("samples", self.fname), encoding="utf-8")
        lexer = MinimalLexer(input_stream)
        stream = CommonTokenStream(lexer)
        parser = MinimalParser(stream)
        tree = parser.text()    # start rule
        printer = MinimalListListener()
        walker = ParseTreeWalker()
        walker.walk(printer, tree)
        self.parsed = printer.tokens # get result stored in the listener

    def tearDown(self):
        self.parsed = []
        
class TestCite1(MinimalTstBase):

    fname = "cite1.txt"

    def test_parsed(self):
        self.assertEqual(
            self.parsed,
            ["A", "B"])

class TestCite2(MinimalTstBase):

    fname = "cite2.txt"

    def test_parsed(self):
        self.assertEqual(
            self.parsed,
            ['c', 'd'])

文件samples/cite1.txt

代码语言:javascript
运行
复制
A B

文件samples/cite2.txt

代码语言:javascript
运行
复制
 c d

文件minimal/__init__.py只是一个空文件。文件setup.py只是样板文件:

代码语言:javascript
运行
复制
from setuptools import find_packages, setup

setup(
    name = "minimal-antlr-testing-example",
    version = "0.0.1",
    description = "Minimal testing example",
    classifiers = [
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    packages = find_packages(where="."),
    python_requires = ">=3.6",
    install_requires = [
        "wheel",
        "setuptools",
        "antlr4-python3-runtime==4.9.1"
        ],
    test_suite = 'minimal',
    )

文件requirements.txt

代码语言:javascript
运行
复制
wheel==0.36.2
antlr4-python3-runtime==4.9.1

运行后

代码语言:javascript
运行
复制
java -cp antlr-4.9.1-complete.jar org.antlr.v4.Tool -o minimal/ \
-Xexact-output-dir -Dlanguage="Python3" Minimal.g4

有以下文件:

代码语言:javascript
运行
复制
./minimal/Minimal.tokens
./minimal/MinimalListener.py
./minimal/MinimalParser.py
./minimal/Minimal.interp
./minimal/MinimalLexer.tokens
./minimal/MinimalLexer.py
./minimal/MinimalLexer.interp
./minimal/test_minimal.py
./minimal/minimal.py
./minimal/__init__.py
./samples/cite2.txt
./samples/cite1.txt
./Minimal.g4
./requirements.txt
./setup.py

安装并运行测试:

代码语言:javascript
运行
复制
python3 -m venv env
source env/bin/activate
python -m pip install -r requirements.txt
python setup.py bdist_wheel
python setup.py test

...

test_parsed (minimal.test_minimal.TestCite1) ... ok
test_parsed (minimal.test_minimal.TestCite2) ... FAIL

======================================================================
FAIL: test_parsed (minimal.test_minimal.TestCite2)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/clueck/src/minimal/antlr/minimal/test_minimal.py", line 46, in test_parsed
    ['c', 'd'])
AssertionError: Lists differ: ['A', 'B', 'c', 'd'] != ['c', 'd']

First differing element 0:
'A'
'c'

First list contains 2 additional elements.
First extra element 2:
'c'

- ['A', 'B', 'c', 'd']
+ ['c', 'd']

如何在运行单元测试时隔离解析器运行?

亲切的问候

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-17 03:39:36

代码语言:javascript
运行
复制
class MinimalListListener(MinimalListener):

    tokens = []

这将创建一个属于MinimalListListener类的列表,该列表在该类的所有实例之间共享。因此,如果创建类的两个实例,这两个实例都将元素添加到列表中,则列表最终将包含来自这两个实例的元素。

要在Python中创建特定于每个实例的变量,请在__init__中设置变量,而不是设置类体:

代码语言:javascript
运行
复制
class MinimalListListener(MinimalListener):
    def __init__(self):
        self.tokens = []
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66654856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档