summaryrefslogtreecommitdiff
path: root/conftest.py
diff options
context:
space:
mode:
authorEevee (Alex Munroe) <eevee.git@veekun.com>2014-08-26 13:03:48 -0700
committerEevee (Alex Munroe) <eevee.git@veekun.com>2014-08-26 14:32:01 -0700
commite045cd72c467eacd16aaee2613ef0850e559a3ce (patch)
treefd6dec2df10907e5f2c912a8ab83f070223e4278 /conftest.py
parent77f24e0a2e8fb394004023191c8662febd8ceda0 (diff)
downloadpyscss-e045cd72c467eacd16aaee2613ef0850e559a3ce.tar.gz
Revamp py.test's handling of test files.
Each .scss file is now its own test -- you can run them directly, with `py.test scss/tests/files/foo/bar.scss`, or use wildcards, or specify a partial directory, or whatever. Accordingly, `test_files.py` is gone, as is the `--test-file-filter` option that was so cumbersome I never actually used it. Regressions: - xfail is no longer supported. - Ruby tests are now not collected at all, rather than marked as skipped.
Diffstat (limited to 'conftest.py')
-rw-r--r--conftest.py110
1 files changed, 102 insertions, 8 deletions
diff --git a/conftest.py b/conftest.py
index 445657d..8019aa8 100644
--- a/conftest.py
+++ b/conftest.py
@@ -1,4 +1,27 @@
"""py.test plugin configuration."""
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import logging
+
+import pytest
+
+import scss
+import scss.config
+
+try:
+ import fontforge
+except ImportError:
+ fontforge = None
+
+
+# Turn on pyscss's logging
+console = logging.StreamHandler()
+logger = logging.getLogger('scss')
+logger.setLevel(logging.ERROR)
+logger.addHandler(console)
+
def pytest_addoption(parser):
"""Add options for filtering which file tests run.
@@ -7,16 +30,87 @@ def pytest_addoption(parser):
recursively look for conftest.py files until after it's parsed the command
line.
"""
- parser.addoption('--include-ruby',
+ parser.addoption(
+ '--include-ruby',
help='run tests imported from Ruby and sassc, most of which fail',
action='store_true',
dest='include_ruby',
)
- parser.addoption('--test-file-filter',
- help='comma-separated regexes to select test files',
- action='store',
- type='string',
- dest='test_file_filter',
- default=None,
- )
+
+def pytest_ignore_collect(path, config):
+ # Ruby/sassc tests don't even exist without this option
+ if path.basename in ('from_ruby', 'from-sassc'):
+ if not config.getoption('include_ruby'):
+ return True
+
+
+def pytest_collect_file(path, parent):
+ if path.ext == '.scss':
+ parts = str(path).split(path.sep)
+ # -4 tests / -3 files / -2 directory / -1 file.scss
+ if parts[-4:-2] == ['tests', 'files']:
+ return SassFile(path, parent)
+
+
+class SassFile(pytest.File):
+ def collect(self):
+ parent_name = self.fspath.dirpath().basename
+ if not fontforge and parent_name == 'fonts':
+ pytest.skip("font tests require fontforge")
+
+ yield SassItem(str(self.fspath), self)
+
+
+class SassItem(pytest.Item):
+ """A Sass test input file, collected as its own test item.
+
+ A file of the same name but with a .css extension is assumed to contain the
+ expected output.
+ """
+ _nodeid = None
+
+ @property
+ def nodeid(self):
+ # Rig the nodeid to be "directory::filename", so all the files in the
+ # same directory are treated as grouped together
+ if not self._nodeid:
+ self._nodeid = "{0}::{1}".format(
+ self.fspath.dirpath().relto(self.session.fspath),
+ self.fspath.basename,
+ )
+ return self._nodeid
+
+ def reportinfo(self):
+ return (
+ self.fspath.dirpath(),
+ None,
+ self.fspath.relto(self.session.fspath),
+ )
+
+ def runtest(self):
+ scss_file = self.fspath
+ css_file = scss_file.new(ext='css')
+
+ with scss_file.open('rb') as fh:
+ source = fh.read()
+ with css_file.open('rb') as fh:
+ # Output is Unicode, so decode this here
+ expected = fh.read().decode('utf8')
+
+ scss.config.STATIC_ROOT = str(scss_file.dirpath('static'))
+
+ compiler = scss.Scss(
+ scss_opts=dict(style='expanded'),
+ search_paths=[
+ str(scss_file.dirpath('include')),
+ str(scss_file.dirname),
+ ],
+ )
+ actual = compiler.compile(source)
+
+ # Normalize leading and trailing newlines
+ actual = actual.strip('\n')
+ expected = expected.strip('\n')
+
+ assert expected == actual