Repository: jamescooke/flake8-aaa

Issue:
Fails when testing unicode files
When file is marked with unicode and contains unicode chars:

```
# encoding: utf-8
```

Then loading the file fails:

```
  File "/home/vagrant/pysyncgateway/venv/local/lib/python2.7/site-packages/flake8/checker.py", line 493, in run_ast_checks
    for (line_number, offset, text, check) in runner:
  File "/home/vagrant/pysyncgateway/venv/local/lib/python2.7/site-packages/flake8_aaa/checker.py", line 42, in run
    self.load()
  File "/home/vagrant/pysyncgateway/venv/local/lib/python2.7/site-packages/flake8_aaa/checker.py", line 34, in load
    self.tree = astroid.parse(file_contents)
  File "/home/vagrant/pysyncgateway/venv/local/lib/python2.7/site-packages/astroid/builder.py", line 282, in parse
    return builder.string_build(code, modname=module_name, path=path)
  File "/home/vagrant/pysyncgateway/venv/local/lib/python2.7/site-packages/astroid/builder.py", line 158, in string_build
    module.file_bytes = data.encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1025: ordinal not in range(128)
```

Example test file is at: https://github.com/constructpm/pysyncgateway/blob/master/tests/document/test_create_update.py

Discussion:

Patch:
diff --git a/flake8_aaa/act_block.py b/flake8_aaa/act_block.py
index 51cd753..a49d5a4 100644
--- a/flake8_aaa/act_block.py
+++ b/flake8_aaa/act_block.py
@@ -23,11 +23,10 @@ class ActBlock:
         self.block_type = block_type
 
     @classmethod
-    def build(obj, node, tokens):
+    def build(obj, node):
         """
         Args:
-            node (astroid.*): An astroid node.
-            tokens (asttokens.ASTTokens): Tokens that contain this node.
+            node (ast.node): A node, decorated with ``ASTTokens``.
 
         Returns:
             ActBlock
@@ -41,8 +40,7 @@ class ActBlock:
             return obj(node, obj.PYTEST_RAISES)
 
         # Check if line marked with '# act'
-        line = next(tokens.get_tokens(node, include_extra=True)).line
-        if line.strip().lower().endswith('# act'):
+        if node.first_token.line.strip().endswith('# act'):
             return obj(node, obj.MARKED_ACT)
 
         raise NotActionBlock()
diff --git a/flake8_aaa/checker.py b/flake8_aaa/checker.py
index cc548c5..1a704f7 100644
--- a/flake8_aaa/checker.py
+++ b/flake8_aaa/checker.py
@@ -1,4 +1,3 @@
-import astroid
 import asttokens
 
 from .__about__ import __short_name__, __version__
@@ -11,28 +10,27 @@ class Checker:
     Attributes:
         ast_tokens (asttokens.ASTTokens): Tokens for the file.
         filename (str): Name of file under check.
-        tree (astroid.Module): Astroid tree loaded from file.
+        lines (list (str))
+        tree (ast.Module): Tree passed from flake8.
     """
 
     name = __short_name__
     version = __version__
 
-    def __init__(self, tree, filename):
+    def __init__(self, tree, lines, filename):
         """
         Args:
-            tree: Ignored, but is required for flake8 to recognise this as a
-                plugin.
+            tree
+            lines (list (str))
             filename (str)
         """
+        self.tree = tree
+        self.lines = lines
         self.filename = filename
-        self.tree = None
         self.ast_tokens = None
 
     def load(self):
-        with open(self.filename) as f:
-            file_contents = f.read()
-        self.tree = astroid.parse(file_contents)
-        self.ast_tokens = asttokens.ASTTokens(file_contents, tree=self.tree)
+        self.ast_tokens = asttokens.ASTTokens(''.join(self.lines), tree=self.tree)
 
     def run(self):
         """
@@ -41,7 +39,7 @@ class Checker:
         if is_test_file(self.filename):
             self.load()
             for function_def in find_test_functions(self.tree):
-                function = Function(function_def, self.ast_tokens)
+                function = Function(function_def)
                 function.parse()
                 for error in function.check():
                     yield error + (type(self), )
diff --git a/flake8_aaa/function.py b/flake8_aaa/function.py
index 6ce9281..e353135 100644
--- a/flake8_aaa/function.py
+++ b/flake8_aaa/function.py
@@ -9,21 +9,18 @@ class Function:
         act_blocks (list (ActBlock)): List of nodes that are considered Act
             blocks for this test. Defaults to ``None`` when function has not
             been parsed.
-        node (astroid.FunctionDef): AST for the test under lint.
-        tokens (asttokens.ASTTokens): Tokens for the file under test.
+        node (ast.FunctionDef): AST for the test under lint.
         is_noop (bool): Function is considered empty. Consists just of comments
             or ``pass``.
         parsed (bool): Function's nodes have been parsed.
     """
 
-    def __init__(self, node, tokens):
+    def __init__(self, node):
         """
         Args:
             node (ast.FunctionDef)
-            tokens (asttokens.ASTTokens)
         """
         self.node = node
-        self.tokens = tokens
         self.act_blocks = []
         self.is_noop = False
         self.parsed = False
@@ -43,9 +40,9 @@ class Function:
             self.is_noop = True
             return 0
 
-        for child_node in self.node.get_children():
+        for child_node in self.node.body:
             try:
-                self.act_blocks.append(ActBlock.build(child_node, self.tokens))
+                self.act_blocks.append(ActBlock.build(child_node))
             except NotActionBlock:
                 continue
 
diff --git a/flake8_aaa/helpers.py b/flake8_aaa/helpers.py
index 1e3309e..c0e7b63 100644
--- a/flake8_aaa/helpers.py
+++ b/flake8_aaa/helpers.py
@@ -1,7 +1,6 @@
+import ast
 import os
 
-import astroid
-
 
 def is_test_file(filename):
     """
@@ -27,58 +26,82 @@ def is_test_file(filename):
     return os.path.basename(filename).startswith('test_')
 
 
+class TestFuncLister(ast.NodeVisitor):
+    """
+    Helper to walk the ast Tree and find functions that looks like tests.
+    Matching function nodes are kept in ``_found_func`` attr.
+
+    Attributes:
+        _found_func (list (ast.node))
+    """
+
+    def __init__(self, *args, **kwargs):
+        super(TestFuncLister, self).__init__(*args, **kwargs)
+        self._found_funcs = []
+
+    def visit_FunctionDef(self, node):
+        if node.name.startswith('test'):
+            self._found_funcs.append(node)
+
+
 def find_test_functions(tree):
     """
     Args:
-        tree (astroid.Module)
+        tree (ast.Module)
 
     Returns:
-        list (astroid.FunctionDef): Fuctions that look like tests.
+        list (ast.FunctionDef): Functions that look like tests.
     """
-    test_nodes = []
-    for node in tree.get_children():
-        if node.is_function and node.name.startswith('test'):
-            test_nodes.append(node)
-    return test_nodes
+    function_finder = TestFuncLister()
+    function_finder.visit(tree)
+    return function_finder._found_funcs
 
 
 def node_is_result_assignment(node):
     """
     Args:
-        node: An ``astroid`` node.
+        node: An ``ast`` node.
 
     Returns:
         bool: ``node`` corresponds to the code ``result =``, assignment to the
         ``result `` variable.
+
+    Note:
+        Performs a very weak test that the line starts with 'result =' rather
+        than testing the tokens.
     """
-    return (
-        isinstance(node, astroid.Assign) and len(node.targets) == 1 and isinstance(node.targets[0], astroid.AssignName)
-        and node.targets[0].name == 'result'
-    )
+    return node.first_token.line.strip().startswith('result =')
 
 
 def node_is_pytest_raises(node):
     """
     Args:
-        node: An ``astroid`` node.
+        node: An ``ast`` node, augmented with ASTTokens
 
     Returns:
         bool: ``node`` corresponds to a With node where the context manager is
         ``pytest.raises``.
     """
-    if (isinstance(node, astroid.With)):
-        child = next(node.get_children())
-        if child.as_string().startswith('pytest.raises'):
-            return True
-    return False
+    return isinstance(node, ast.With) and node.first_token.line.strip().startswith('with pytest.raises')
+
+
+def node_is_noop(node):
+    """
+    Args:
+        node (ast.node)
+
+    Returns:
+        bool: Node does nothing.
+    """
+    return (type(node) is ast.Expr and type(node.value) is ast.Str) or (type(node) is ast.Pass)
 
 
 def function_is_noop(function_node):
     """
     Args:
-        function_node (astroid.FunctionDef): A function.
+        function_node (ast.FunctionDef): A function.
 
     Returns:
         bool: Function does nothing - is just ``pass`` or docstring.
     """
-    return all(type(node) is astroid.Pass for node in function_node.body)
+    return all(node_is_noop(n) for n in function_node.body)
diff --git a/requirements/base.in b/requirements/base.in
index 92fe705..e65fd57 100644
--- a/requirements/base.in
+++ b/requirements/base.in
@@ -1,3 +1,2 @@
-astroid>=1.6
 asttokens>=1.1.10
 flake8>=3
diff --git a/requirements/base.txt b/requirements/base.txt
index b20300d..c02ba77 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -4,12 +4,9 @@
 #
 #    pip-compile --output-file base.txt base.in
 #
-astroid==1.6.3
 asttokens==1.1.10
 flake8==3.5.0
-lazy-object-proxy==1.3.1  # via astroid
 mccabe==0.6.1             # via flake8
 pycodestyle==2.3.1        # via flake8
 pyflakes==1.6.0           # via flake8
-six==1.11.0               # via astroid, asttokens
-wrapt==1.10.11            # via astroid
+six==1.11.0               # via asttokens
diff --git a/requirements/dev.txt b/requirements/dev.txt
index f385fef..3e8bddd 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -4,7 +4,6 @@
 #
 #    pip-compile --output-file dev.txt dev.in
 #
-astroid==1.6.3
 asttokens==1.1.10
 attrs==18.1.0
 backcall==0.1.0           # via ipython
@@ -21,7 +20,6 @@ ipython-genutils==0.2.0   # via traitlets
 ipython==6.4.0
 isort==4.3.4
 jedi==0.12.0              # via ipython
-lazy-object-proxy==1.3.1
 mccabe==0.6.1
 more-itertools==4.1.0
 parso==0.2.0              # via jedi
@@ -50,5 +48,4 @@ twine==1.11.0
 urllib3==1.22             # via requests
 virtualenv==15.2.0
 wcwidth==0.1.7            # via prompt-toolkit
-wrapt==1.10.11
 yapf==0.21.0
diff --git a/setup.py b/setup.py
index ecfa361..830807d 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ def readme():
 
 about = {}
 with open(os.path.join(basedir, 'flake8_aaa', '__about__.py')) as f:
-    exec(f.read(), about)
+    exec(f.read(), about)  # yapf: disable
 
 setup(
     # --- META ---
@@ -31,7 +31,6 @@ setup(
     packages=['flake8_aaa'],
     py_modules=['flake8_aaa'],
     install_requires=[
-        'astroid >= 1.6',
         'asttokens >= 1.1.10',
         'flake8 >= 3',
     ],
diff --git a/tox.ini b/tox.ini
index a562e6e..aa37fc8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,11 @@
-# install = assert that plugin can be installed and run via flake8 in a clean venv
+# install = assert that plugin can be installed and run via flake8 in a clean
+#   venv
 # test = run pytest
-# lint = run all linting
+# lint = run all linting, including on the test suite. Use both py2 and py3 to
+#   ensure that unicode loads OK.
 
 [tox]
-envlist = py{27,36}-{install,test},py36-lint
+envlist = py{27,36}-{install,test,lint}
 [testenv]
 deps =
     test,lint: -rrequirements/test.txt


Test patch:
diff --git a/requirements/test.txt b/requirements/test.txt
index df21662..3d9c456 100644
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -4,13 +4,11 @@
 #
 #    pip-compile --output-file test.txt test.in
 #
-astroid==1.6.3
 asttokens==1.1.10
 attrs==18.1.0             # via pytest
 docutils==0.14            # via restructuredtext-lint
 flake8==3.5.0
 isort==4.3.4
-lazy-object-proxy==1.3.1
 mccabe==0.6.1
 more-itertools==4.1.0     # via pytest
 pluggy==0.6.0             # via pytest, tox
@@ -23,5 +21,4 @@ restructuredtext-lint==1.1.3
 six==1.11.0
 tox==3.0.0
 virtualenv==15.2.0        # via tox
-wrapt==1.10.11
 yapf==0.21.0
diff --git a/tests/act_block/test_build.py b/tests/act_block/test_build.py
index 6dfb9cb..d8dd526 100644
--- a/tests/act_block/test_build.py
+++ b/tests/act_block/test_build.py
@@ -1,10 +1,28 @@
-import astroid
-import asttokens
 import pytest
 
 from flake8_aaa.act_block import ActBlock
 from flake8_aaa.exceptions import NotActionBlock
 
+# TODO act blocks need testing with 'result =' indented
+# TODO act blocks need testing with indentation in general
+
+
+@pytest.mark.parametrize(
+    'code_str', [
+        """
+def test_not_actions(first_node_with_tokens):
+    with pytest.raises(NotActionBlock):
+        ActBlock.build(first_node_with_tokens)
+"""
+    ]
+)
+def test_raises_block(first_node_with_tokens):
+    result = ActBlock.build(first_node_with_tokens.body[0])
+
+    assert isinstance(result, ActBlock)
+    assert result.node == first_node_with_tokens.body[0]
+    assert result.block_type == ActBlock.PYTEST_RAISES
+
 
 @pytest.mark.parametrize(
     'code_str, expected_type', [
@@ -13,14 +31,11 @@ from flake8_aaa.exceptions import NotActionBlock
         ('data[new_key] = value  # act', ActBlock.MARKED_ACT),
     ]
 )
-def test(code_str, expected_type):
-    node = astroid.extract_node(code_str)
-    tokens = asttokens.ASTTokens(code_str, tree=node)
-
-    result = ActBlock.build(node, tokens)
+def test(expected_type, first_node_with_tokens):
+    result = ActBlock.build(first_node_with_tokens)
 
     assert isinstance(result, ActBlock)
-    assert result.node == node
+    assert result.node == first_node_with_tokens
     assert result.block_type == expected_type
 
 
@@ -34,9 +49,6 @@ def test(code_str, expected_type):
         'with open("data.txt") as f:\n    f.read()',
     ]
 )
-def test_not_actions(code_str):
-    node = astroid.extract_node(code_str)
-    tokens = asttokens.ASTTokens(code_str, tree=node)
-
+def test_not_actions(first_node_with_tokens):
     with pytest.raises(NotActionBlock):
-        ActBlock.build(node, tokens)
+        ActBlock.build(first_node_with_tokens)
diff --git a/tests/checker/test_init.py b/tests/checker/test_init.py
index b091b9c..efc8e91 100644
--- a/tests/checker/test_init.py
+++ b/tests/checker/test_init.py
@@ -2,8 +2,9 @@ from flake8_aaa import Checker
 
 
 def test():
-    result = Checker(None, '__FILENAME__')
+    result = Checker(None, [], '__FILENAME__')
 
-    assert result.filename == '__FILENAME__'
     assert result.tree is None
+    assert result.lines == []
+    assert result.filename == '__FILENAME__'
     assert result.ast_tokens is None
diff --git a/tests/checker/test_load.py b/tests/checker/test_load.py
index 3f0962e..2ff2734 100644
--- a/tests/checker/test_load.py
+++ b/tests/checker/test_load.py
@@ -1,16 +1,17 @@
-import astroid
+import ast
 
 from flake8_aaa import Checker
 
 
 def test(tmpdir):
     target_file = tmpdir.join('test.py')
-    target_file.write('assert 1 + 2 == 3')
-    checker = Checker(None, target_file.strpath)
+    target_file.write('assert 1 + 2 == 3\n')
+    tree = ast.parse(target_file.read())
+    checker = Checker(tree, ['assert 1 + 2 == 3\n'], target_file.strpath)
 
     result = checker.load()
 
     assert result is None
     assert len(checker.tree.body) == 1
-    assert type(checker.tree.body[0]) == astroid.Assert
-    assert len(checker.ast_tokens.tokens) == 7
+    assert type(checker.tree.body[0]) == ast.Assert
+    assert len(checker.ast_tokens.tokens) == 8
diff --git a/tests/conftest.py b/tests/conftest.py
index dd37e10..98682c2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,6 @@
+import ast
+
+import asttokens
 import pytest
 from flake8.defaults import MAX_LINE_LENGTH
 from flake8.processor import FileProcessor
@@ -48,3 +51,17 @@ def first_token(file_tokens):
         First token of provided list.
     """
     return file_tokens[0]
+
+
+@pytest.fixture
+def first_node_with_tokens(code_str):
+    """
+    Given ``code_str`` fixture, parse that string with ``ast.parse`` and then
+    augment it with ``asttokens.ASTTokens``.
+
+    Returns:
+        ast.node: First node in parsed tree.
+    """
+    tree = ast.parse(code_str)
+    asttokens.ASTTokens(code_str, tree=tree)
+    return tree.body[0]
diff --git a/tests/function/conftest.py b/tests/function/conftest.py
index 79c5d89..3949659 100644
--- a/tests/function/conftest.py
+++ b/tests/function/conftest.py
@@ -1,32 +1,12 @@
-import astroid
-import asttokens
 import pytest
 
 from flake8_aaa.function import Function
 
 
 @pytest.fixture
-def function_node(code_str):
+def function(first_node_with_tokens):
     """
-    Args:
-        code_str (str): Should contain only one function which can be
-            extracted.
-
-    Returns:
-        astroid.FunctionDef
-    """
-    return astroid.extract_node(code_str)
-
-
-@pytest.fixture
-def function(function_node, code_str):
-    """
-    Args:
-        function_node (astroid.FunctionDef)
-        code_str (str)
-
     Returns:
-        Function
+        Function: Loaded with ``first_node_with_tokens`` node.
     """
-    tokens = asttokens.ASTTokens(code_str, tree=function_node)
-    return Function(function_node, tokens)
+    return Function(first_node_with_tokens)
diff --git a/tests/function/test_fixtures.py b/tests/function/test_fixtures.py
index 8f64ce9..015916f 100644
--- a/tests/function/test_fixtures.py
+++ b/tests/function/test_fixtures.py
@@ -1,4 +1,5 @@
-import astroid
+import ast
+
 import pytest
 
 
@@ -6,11 +7,11 @@ import pytest
 def test():
     pass  # act
 """])
-def test(function):
-    result = function
+def test(first_node_with_tokens):
+    result = first_node_with_tokens
 
-    assert result.node.name == 'test'
-    pass_node = list(result.node.get_children())[-1]
-    assert isinstance(pass_node, astroid.Pass)
-    first_pass_token = next(result.tokens.get_tokens(pass_node, include_extra=True))
-    assert first_pass_token.line.strip().endswith('# act')
+    assert result.name == 'test'
+    assert len(result.body) == 1
+    pass_node = result.body[0]
+    assert isinstance(pass_node, ast.Pass)
+    assert pass_node.first_token.line.strip().endswith('# act')
diff --git a/tests/function/test_init.py b/tests/function/test_init.py
index 904863c..3761e43 100644
--- a/tests/function/test_init.py
+++ b/tests/function/test_init.py
@@ -1,20 +1,16 @@
-import asttokens
 import pytest
 
 from flake8_aaa.function import Function
 
 
 @pytest.mark.parametrize('code_str', ['''
-    def test():
-        pass
-    '''])
-def test(function_node, code_str):
-    tokens = asttokens.ASTTokens(code_str, tree=function_node)
+def test():
+    pass
+'''])
+def test(first_node_with_tokens):
+    result = Function(first_node_with_tokens)
 
-    result = Function(function_node, tokens)
-
-    assert result.node == function_node
-    assert result.tokens == tokens
+    assert result.node == first_node_with_tokens
     assert result.act_blocks == []
     assert result.parsed is False
     assert result.is_noop is False
diff --git a/tests/function/test_parse.py b/tests/function/test_parse.py
index 4cb1d7e..910d0cd 100644
--- a/tests/function/test_parse.py
+++ b/tests/function/test_parse.py
@@ -23,19 +23,19 @@ def test_one(function):
 @pytest.mark.parametrize(
     'code_str', [
         '''
-    def test(user):
-        result = login(user)  # Logging in User returns True
-        assert result is True
+def test(user):
+    result = login(user)  # Logging in User returns True
+    assert result is True
 
-        result = login(user)  # Already logged in User returns False
-        assert result is False
+    result = login(user)  # Already logged in User returns False
+    assert result is False
     ''',
         '''
-    def test():
-        chickens = 1  # act
-        eggs = 1  # act
+def test():
+    chickens = 1  # act
+    eggs = 1  # act
 
-        assert chickens + eggs == 2
+    assert chickens + eggs == 2
     ''',
     ]
 )
diff --git a/tests/helpers/test_find_test_functions.py b/tests/helpers/test_find_test_functions.py
index 8067a86..b1b1245 100644
--- a/tests/helpers/test_find_test_functions.py
+++ b/tests/helpers/test_find_test_functions.py
@@ -1,10 +1,10 @@
-import astroid
+import ast
 
 from flake8_aaa.helpers import find_test_functions
 
 
 def test_empty():
-    tree = astroid.parse("print('hi')")
+    tree = ast.parse("print('hi')")
 
     result = find_test_functions(tree)
 
@@ -12,7 +12,7 @@ def test_empty():
 
 
 def test_some():
-    tree = astroid.parse(
+    tree = ast.parse(
         """
 import pytest
 
diff --git a/tests/helpers/test_function_is_noop.py b/tests/helpers/test_function_is_noop.py
index 057038a..ae1b2cf 100644
--- a/tests/helpers/test_function_is_noop.py
+++ b/tests/helpers/test_function_is_noop.py
@@ -1,4 +1,5 @@
-import astroid
+import ast
+
 import pytest
 
 from flake8_aaa.helpers import function_is_noop
@@ -11,7 +12,7 @@ from flake8_aaa.helpers import function_is_noop
     ]
 )
 def test(code_str):
-    node = astroid.extract_node(code_str)
+    node = ast.parse(code_str).body[0]
 
     result = function_is_noop(node)
 
@@ -22,7 +23,7 @@ def test(code_str):
     'def test_tomorrow():\n    # TODO write this test\n    result = 1',
 ])
 def test_not_noop(code_str):
-    node = astroid.extract_node(code_str)
+    node = ast.parse(code_str).body[0]
 
     result = function_is_noop(node)
 
diff --git a/tests/helpers/test_node_is_pytest_raises.py b/tests/helpers/test_node_is_pytest_raises.py
index 9a21de3..1e87e7b 100644
--- a/tests/helpers/test_node_is_pytest_raises.py
+++ b/tests/helpers/test_node_is_pytest_raises.py
@@ -1,4 +1,6 @@
-import astroid
+import ast
+
+import asttokens
 import pytest
 
 from flake8_aaa.helpers import node_is_pytest_raises
@@ -6,15 +8,22 @@ from flake8_aaa.helpers import node_is_pytest_raises
 
 @pytest.mark.parametrize(
     'code_str', [
-        '''with pytest.raises(Exception):
-    do_thing()''', '''with pytest.raises(Exception) as excinfo:
-    do_thing()'''
+        '''
+def test():
+    with pytest.raises(Exception):
+        do_thing()
+''',
+        '''
+def test_other():
+    with pytest.raises(Exception) as excinfo:
+        do_thing()
+''',
     ]
 )
-def test(code_str):
-    node = astroid.parse(code_str).body[0]
+def test(first_node_with_tokens):
+    with_node = first_node_with_tokens.body[0]
 
-    result = node_is_pytest_raises(node)
+    result = node_is_pytest_raises(with_node)
 
     assert result is True
 
@@ -24,7 +33,9 @@ def test(code_str):
     f.read()''',
 ])
 def test_no(code_str):
-    node = astroid.parse(code_str).body[0]
+    tree = ast.parse(code_str)
+    asttokens.ASTTokens(code_str, tree=tree)
+    node = tree.body[0]
 
     result = node_is_pytest_raises(node)
 
diff --git a/tests/helpers/test_node_is_result_assignment.py b/tests/helpers/test_node_is_result_assignment.py
index ec85e03..ce87c34 100644
--- a/tests/helpers/test_node_is_result_assignment.py
+++ b/tests/helpers/test_node_is_result_assignment.py
@@ -1,33 +1,21 @@
-import astroid
 import pytest
 
 from flake8_aaa.helpers import node_is_result_assignment
 
 
-@pytest.mark.parametrize('code_str', (
-    'result = 1',
-    'result = lambda x: x + 1',
-))
-def test(code_str):
-    node = astroid.extract_node(code_str)
-
-    result = node_is_result_assignment(node)
-
-    assert result is True
-
-
 @pytest.mark.parametrize(
-    'code_str', (
-        'xresult = 1',
-        'result, _ = 1, 2',
-        'result[0] = 0',
-        'result += 1',
-        'result -= 1',
-    )
+    ('code_str', 'expected_result'),
+    [
+        ('result = 1', True),
+        ('result = lambda x: x + 1', True),
+        ('xresult = 1', False),
+        ('result, _ = 1, 2', False),
+        ('result[0] = 0', False),
+        ('result += 1', False),
+        ('result -= 1', False),
+    ],
 )
-def test_no(code_str):
-    node = astroid.parse(code_str).body[0]
-
-    result = node_is_result_assignment(node)
+def test_no(first_node_with_tokens, expected_result):
+    result = node_is_result_assignment(first_node_with_tokens)
 
-    assert result is False
+    assert result is expected_result
diff --git a/tests/test_run.py b/tests/test_run.py
index 0d05296..bb0b7a6 100644
--- a/tests/test_run.py
+++ b/tests/test_run.py
@@ -1,5 +1,9 @@
+# encoding: utf-8
+
 # Integration tests that flake8 runs and checks using this plugin
 
+# Some unicode text: Réne has £10 - ensure that this file is loaded with Python 2
+
 from flake8_aaa.__about__ import __version__