Skip to content
This repository was archived by the owner on Sep 21, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
htmlcov
.ropeproject*
__pycache__

# Neovim remote plugin manifested generated by make
ensime_shared/spec/resources/.vimrc-rplugin~
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
PYTHON := python2
VENV ?= .venv
NVIM := nvim

# autopep8 uses pycodestyle but doesn't automatically find files the same way :-/
REFORMAT := ensime_shared/ rplugin/
Expand All @@ -9,6 +10,10 @@ requirements := requirements.txt test-requirements.txt
deps := $(VENV)/deps-updated

features := test/features
test_resources := test/resources
vimrc := $(test_resources)/vimrc
rplugin_manifest := $(test_resources)/.vimrc-rplugin~


test: unit integration

Expand All @@ -24,7 +29,7 @@ unit: $(deps)
@echo "Running ensime-vim unit tests"
. $(activate) && py.test

integration: $(deps)
integration: $(deps) $(rplugin_manifest)
@echo "Running ensime-vim lettuce tests"
. $(activate) && lettuce $(features)

Expand All @@ -50,9 +55,13 @@ clean:
-find . -type d -name '__pycache__' -delete
. $(activate) && coverage erase
-$(RM) -r htmlcov
-$(RM) $(rplugin_manifest)

distclean: clean
@echo Cleaning the virtualenv...
-rm -rf $(VENV)

.PHONY: test unit integration coverage lint format clean distclean

$(rplugin_manifest): rplugin/python/ensime.py
$(NVIM) -u $(vimrc) -c 'UpdateRemotePlugins' -c 'quit'
2 changes: 2 additions & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# === Test ===
coverage~=4.2
lettuce~=0.2.21
neovim~=0.1
psutil~=4.3
pytest~=2.9

# Optional speed-up for Lettuce, but Docker image build issue needs fixing, see:
Expand Down
29 changes: 0 additions & 29 deletions test/features/ensime_harness.py

This file was deleted.

18 changes: 18 additions & 0 deletions test/features/server_bootstrap.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Feature: Server bootstrap and launch
In order to use ENSIME from my editor
As a plugin user
I want to have the server installed and launched automatically

Scenario: First-time Setup
Given no server bootstrap project exists
And I have created a valid .ensime project config
When I edit a Scala file
And invoke server installation
Then ENSIME should be installed
And the server should be started

Scenario: Begin an editing session with server installed
Given I have installed ENSIME server
And I have created a valid .ensime project config
When I edit a Scala file
Then the server should be started
66 changes: 66 additions & 0 deletions test/features/server_bootstrap_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import os
import shutil
import subprocess
from os import path

import psutil
from lettuce import step, world

from ensime_shared.config import ProjectConfig


@step('no server bootstrap project exists')
def recreate_boostrap_project_path(step):
bootstraps = world.bootstrap_projects_path
shutil.rmtree(bootstraps)
os.mkdir(bootstraps)


@step('I have installed ENSIME server')
def install_ensime(step):
"""Rely on the existing test environment state to save some time..."""
# step.given('no server bootstrap project exists')
# step.given('invoke server installation')
pass


@step('have created a valid .ensime project config')
def set_valid_dot_ensime(step):
with world.project_directory() as here:
failed = subprocess.call(['sbt', 'ensimeConfig'])
assert not bool(failed), \
'sbt ensimeConfig exited with status {}'.format(failed)

dotensime = path.join(here, '.ensime')
config = ProjectConfig.parse(dotensime)
assert config.get('scala-version') == '2.11.8'


@step('I edit a Scala file')
def edit_scala_file(step):
world.vim.command('edit src/main/scala/Main.scala')


@step('invoke server installation')
def run_en_install(step):
world.vim.command('EnInstall')


@step('ENSIME should be installed')
def server_is_installed(step):
# TODO: use bootstrap_projects_path when that works
classpath_path = path.expanduser('~/.config/ensime-vim/2.11.8/classpath')
assert path.exists(path.realpath(classpath_path))


@step('the server should be started')
def server_is_started(step):
pid_path = path.join(world.project_path, '.ensime_cache', 'server.pid')
assert path.exists(path.realpath(pid_path))

with open(pid_path) as pidfile:
pid = int(pidfile.read().strip())

assert psutil.pid_exists(pid)
proc = psutil.Process(pid)
assert 'ensime' in ' '.join(proc.cmdline()), proc.cmdline()
115 changes: 115 additions & 0 deletions test/features/terrain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""
Shared test setup such as setup/teardown hooks and fixtures.

This file is loaded automatically by Lettuce, see:
http://lettuce.it/reference/terrain.html
"""

import os
import shutil
import sys
import tempfile
from contextlib import contextmanager
from os import path

import neovim
from lettuce import after, before, world

DEBUG = os.environ.get('DEBUG')
LISTEN_ADDRESS = os.environ.get('NVIM_LISTEN_ADDRESS')

FEATURESROOT = path.dirname(path.abspath(__file__))

neovim.setup_logging()


# TODO: Will we need a @before.each_feature that nukes .ensime_cache, etc.?
@before.all
def setup_test_environment():
world.project_path = path.join(tempfile.mkdtemp(), 'testproject')
world.bootstrap_projects_path = tempfile.mkdtemp()

resources = path.realpath(path.join(FEATURESROOT, '..', 'resources'))
shutil.copytree(path.join(resources, 'testproject'), world.project_path)
world.vimrc = path.join(resources, 'vimrc')


@after.all
def teardown_test_environment(_total):
if DEBUG:
print('-' * 80)
print('Project: ' + world.project_path)
print('Bootstraps: ' + world.bootstrap_projects_path)
print('Left for inspection.')
print('-' * 80)
else:
world.vim.quit() # Implicitly shut server down
shutil.rmtree(world.project_path)
shutil.rmtree(world.bootstrap_projects_path)


@before.each_scenario
def reset_vim(_scenario):
# Boilerplate to set up embedded Neovim test instance, by default, allowing
# separate process optionally.
if LISTEN_ADDRESS:
world.vim = neovim.attach('socket', path=LISTEN_ADDRESS)
else:
embed_cmd = ['nvim', '-u', world.vimrc, '-i', 'NONE', '--embed']
world.vim = neovim.attach('child', argv=embed_cmd)

world.vim.input(CLEANUP_FUNC.format(vimrc=world.vimrc))
world.vim.command('call BeforeEachTest()')
assert len(world.vim.tabpages) == 1
assert len(world.vim.windows) == 1
assert len(world.vim.buffers) == 1


@world.absorb
@contextmanager
def project_directory():
"""Change to the temp test project directory, and yield its path."""
currentdir = os.getcwd()
project = world.project_path
try:
os.chdir(project)
world.vim.command('cd ' + project)
yield world.project_path
finally:
os.chdir(currentdir)

# Cribbed from neovim/python-client, amended to NOT clear stuff like
# autocommands that would break our plugin. There's no way to reload remote
# plugins currently, the remote#host#LoadRemotePlugins() vimscript function
# throws an error if you re-load an already-registered plugin.
#
# I asked in Neovim Gitter, maybe this will be doable in the future.
CLEANUP_FUNC = """:silent function! BeforeEachTest()
set all&
tabnew
let curbufnum = eval(bufnr('%'))
redir => buflist
silent ls!
redir END
let bufnums = []
for buf in split(buflist, '\\n')
let bufnum = eval(split(buf, '[ u]')[0])
if bufnum != curbufnum
call add(bufnums, bufnum)
endif
endfor
if len(bufnums) > 0
exe 'silent bwipeout! '.join(bufnums, ' ')
endif
silent tabonly
for k in keys(g:)
exe 'unlet g:'.k
endfor
filetype plugin indent off
mapclear
mapclear!
abclear

source {vimrc}
endfunction
"""
5 changes: 5 additions & 0 deletions test/resources/testproject/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name := "ensime-vim-testproject"
organization := "org.ensime"
version := "0.1-SNAPSHOT"
homepage := Some(url("https://github.com/ensime/ensime-vim"))
scalaVersion := "2.11.8"
1 change: 1 addition & 0 deletions test/resources/testproject/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=0.13.11
1 change: 1 addition & 0 deletions test/resources/testproject/project/ensime.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("org.ensime" % "sbt-ensime" % "1.0.0")
3 changes: 3 additions & 0 deletions test/resources/testproject/src/main/scala/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Main extends App {
println("Hello, world!")
}
11 changes: 11 additions & 0 deletions test/resources/vimrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set nowritebackup
set nobackup
set noswapfile

" Exclude user runtime files searched by default
let &runtimepath = $VIMRUNTIME
exec 'set runtimepath+=' . expand('<sfile>:p:h:h:h')

runtime plugin/ensime.vim

filetype plugin on