1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
"""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.
This has to be done in the project root; py.test doesn't (and can't)
recursively look for conftest.py files until after it's parsed the command
line.
"""
parser.addoption(
'--include-ruby',
help='run tests imported from Ruby and sassc, most of which fail',
action='store_true',
dest='include_ruby',
)
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 _prunetraceback(self, excinfo):
# Traceback implements __getitem__, but list implements __getslice__,
# which wins in Python 2
excinfo.traceback = excinfo.traceback.cut(__file__)
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
|