follow narval v4 API changes (closes #2557390)
authorDavid Douard <david.douard@logilab.fr>
Tue, 23 Jul 2013 15:12:25 +0200
changeset 1006 e50f134e41b7
parent 1005 0dff68de958e
child 1007 0f8e2403d4d4
follow narval v4 API changes (closes #2557390) - recipes are now simple Python scripts stored in Plan.script, - no more "arguments" on the Plan CW entity, - add functional tests.
__pkginfo__.py
_apycotlib/__init__.py
_apycotlib/atest.py
_apycotlib/narvalactions.py
entities.py
narval/apycot.py
recipes.py
test/data/project/__init__.py
test/data/project/__pkginfo__.py
test/data/project/setup.py
test/test_functional.py
test/unittest_entities.py
test/unittest_task.py
test/utils.py
--- a/__pkginfo__.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/__pkginfo__.py	Tue Jul 23 15:12:25 2013 +0200
@@ -4,7 +4,7 @@
 modname = 'apycot'
 distname = 'apycot'
 
-numversion = (2, 2, 7)
+numversion = (3, 0, 0) 
 version = '.'.join(str(num) for num in numversion)
 
 license = 'GPL'
--- a/_apycotlib/__init__.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/_apycotlib/__init__.py	Tue Jul 23 15:12:25 2013 +0200
@@ -30,8 +30,6 @@
 
 from cubes import narval # ensure narvalbot is importable
 
-from narvalbot.prototype import action, input
-
 # regitry of available repositories, preprocessors and checkers
 
 REGISTRY = {'repository': {},
@@ -69,19 +67,6 @@
             test.run_checker(id, nonexecuted=True)
     return function
 
-def apycotaction(id, *conditions):
-    """apycotaction : narval action + 'apycot' input being the :class:`Test`
-    instance and 'options' optional input containing configuration options
-    (:class:`narvalbot.elements.Options`)
-    """
-    def decorator(func, id=id):
-        return input('apycot', 'isinstance(elmt, Test)', *conditions)(
-            input('options', 'isinstance(elmt, Options)', optional=True)(
-                action('apycot.%s' % id, nonexecuted=not_executed_checker(id))(func)
-                )
-            )
-    return decorator
-
 
 # check statuses ###############################################################
 
--- a/_apycotlib/atest.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/_apycotlib/atest.py	Tue Jul 23 15:12:25 2013 +0200
@@ -61,16 +61,17 @@
 class Test(object):
     """the single source unit test class"""
 
-    def __init__(self, texec, writer, options):
+    def __init__(self, texec, writer):
+        options = texec.options_dict()
         # directory where the test environment will be built
         self.tmpdir = tempfile.mkdtemp(dir=options.get('test_dir'))
         # notify some subprocesses they're executed by apycot through an
         # environment variable
         os.environ['APYCOT_ROOT'] = self.tmpdir
         # test config / tested project environment
+        self.texec = texec
         self.tconfig = texec.configuration
         self.environment = texec.environment
-        self.branch = texec.branch
         # IWriter object
         self.writer = writer
         # local caches
@@ -126,7 +127,7 @@
                 raise Exception('Project environment %s has no repository' % pe.dc_title())
             repdef = {'repository': pe.repository,
                       'path': pe.vcs_path,
-                      'branch': self.branch}
+                      'branch': self.texec.branch}
             # don't overwrite branch hardcoded on the environment: have to be
             # done here, not only in when starting plan (eg in entities.py)
             # since project env may not be the tested project env
@@ -260,12 +261,11 @@
                               path=path, tb=True)
             self._failed_pp.add(pptype)
 
-    def run_checker(self, id, options=None, nonexecuted=False):
+    def run_checker(self, id, nonexecuted=False, **kwargs):
         """run all checks in the test environment"""
-        if options is None:
-            options = {}
-        else:
-            self._substitute(self.environment, options)
+        options = self.texec.options_dict()
+        options.update(kwargs)
+        self._substitute(self.environment, options)
         check_writer = self.writer.make_check_writer()
         if nonexecuted:
             check_writer.start(id)
@@ -291,7 +291,7 @@
             status = KILLED
             raise
         except MemoryError:
-            check_writer.fatal('memory resource limit reached, arborted')
+            check_writer.fatal('memory resource limit reached, aborted')
             status = KILLED
             raise
         except Exception, ex:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_apycotlib/narvalactions.py	Tue Jul 23 15:12:25 2013 +0200
@@ -0,0 +1,27 @@
+from apycotlib import atest, writer, ERROR
+from apycotlib import preprocessors # trigger registration
+from apycotlib.checkers import python # trigger registration
+
+class apycot_environment(object):
+    def __init__(self, plan):
+        self.plan = plan
+
+    def __enter__(self):
+        w  = writer.TestDataWriter(self.plan.cnxh, self.plan.cwplan.eid)
+        test = atest.Test(self.plan.cwplan, w)
+        test.setup()
+        self.test = test
+        return test
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        if exc_type is not None:
+            self.test.global_status = ERROR
+        self.test.clean()
+
+
+def install_environment(test):
+    tconfig = test.tconfig
+    environment = test.environment
+    for dep in tconfig.dependencies(environment) + [environment]:
+        test.checkout(dep)
+        test.call_preprocessor('install', dep)
--- a/entities.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/entities.py	Tue Jul 23 15:12:25 2013 +0200
@@ -282,11 +282,6 @@
             branch = self.apycot_configuration().get('branch')
         if branch is None:
             branch = pe.repository.default_branch()
-        cfg = self.apycot_configuration(pe)
-        if cfg:
-            arguments = u'Options(%s)' % cfg
-        else:
-            arguments = u'Options(%s)' % cfg
         duplicate_rset = check_duplicate and self._cw.execute(
             "Any X WHERE X branch %(branch)s, X status 'waiting execution', "
             "X using_environment PE, PE eid %(pe)s, "
@@ -306,10 +301,13 @@
             #                 if not dup_arch:
             #                     duplicate.set_attributes(archive=False)
         else:
-            options = u'archive=%s' % archive if archive else u''
+            options = self.apycot_configuration(pe)
+            if archive:
+                options['archive'] = archive
+            options_str = u'\n'.join(u"%s=%s" % kv for kv in options.iteritems())
             texec = self._cw.create_entity(
-                'TestExecution', priority=priority, arguments=arguments,
-                options=options, execution_of=self.recipe,
+                'TestExecution', priority=priority,
+                options=options_str, execution_of=self.recipe,
                 branch=branch, using_environment=pe, using_config=self)
         if start_rev_deps or (start_rev_deps is None and self.start_reverse_dependencies):
             for dpe in pe.reverse_dependencies():
--- a/narval/apycot.py	Wed Aug 07 10:46:21 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-import os
-import os.path as osp
-import subprocess
-
-# setup the import machinery, necessary in dev environment
-from cubes import narval, apycot
-
-import apycotlib
-from apycotlib import atest, writer
-from apycotlib.checkers import BaseChecker
-
-from narvalbot.prototype import EXPR_CONTEXT, action, input, output
-from narvalbot.elements import FilePath
-
-
-def _apycot_cleanup(plan):
-    if hasattr(plan, 'apycot'):
-        if plan.state != 'done':
-            plan.apycot.global_status = apycotlib.ERROR
-        plan.apycot.clean()
-    # XXX clean_env
-
-def _make_test_runner_action(runner):
-    @output('coverage.data', 'isinstance(elmt, FilePath)', optional=True)
-    @apycotlib.apycotaction(runner, 'INSTALLED in elmt.done_steps')
-    def act_runtests(inputs, runner=runner):
-        from apycotlib.checkers import python # trigger registration
-        test = inputs['apycot']
-        options = inputs.get('options')
-        checker, status = test.run_checker(runner, options=options)
-        if options.get('pycoverage') and hasattr(checker, 'coverage_data'):
-            return {'coverage.data': FilePath(checker.coverage_data,
-                                              type='coverage.data')}
-        return {}
-    return act_runtests
-
-
-STEP_CHECKEDOUT, STEP_INSTALLED, STEP_COVERED, STEP_DEBIANPKG = range(4)
-
-EXPR_CONTEXT['Test'] = atest.Test
-EXPR_CONTEXT['CHECKEDOUT'] = STEP_CHECKEDOUT
-EXPR_CONTEXT['INSTALLED']  = STEP_INSTALLED
-EXPR_CONTEXT['COVERED']    = STEP_COVERED
-EXPR_CONTEXT['DEBIANPKG']  = STEP_DEBIANPKG
-
-# base actions #################################################################
-
-@input('plan', 'isinstance(elmt, Plan)')
-@output('apycot',)
-@output('projectenv',)
-@action('apycot.init', finalizer=_apycot_cleanup)
-def act_apycot_init(inputs):
-    plan = inputs['plan']
-    w = writer.TestDataWriter(plan.memory.cnxh, plan.cwplan.eid)
-    test = plan.apycot = atest.Test(plan.cwplan, w, plan.options)
-    test.setup()
-    test.done_steps = set()
-    return {'apycot': test, 'projectenv': test.environment}
-
-
-@input('apycot', 'isinstance(elmt, Test)')
-@output('projectenvs', list=True)
-@action('apycot.get_dependencies')
-def act_get_dependencies(inputs):
-    """Checkout repository for a test configuration"""
-    tconfig = inputs['apycot'].tconfig
-    environment = inputs['apycot'].environment
-    return {'projectenvs': [environment] + tconfig.dependencies(environment)}
-
-
-@input('apycot', 'isinstance(elmt, Test)')
-@input('projectenv', 'getattr(elmt, "__regid__", None) == "ProjectEnvironment"')
-@action('apycot.checkout')
-def act_checkout(inputs):
-    """Checkout repository for a test configuration"""
-    test = inputs['apycot']
-    test.checkout(inputs['projectenv'])
-    test.done_steps.add(STEP_CHECKEDOUT)
-    return {}
-
-
-@input('projectenv', 'getattr(elmt, "__regid__", None) == "ProjectEnvironment"')
-@input('apycot', 'isinstance(elmt, Test)', 'CHECKEDOUT in elmt.done_steps')
-@action('apycot.install')
-def act_install(inputs):
-    from apycotlib import preprocessors
-    test = inputs['apycot']
-    test.call_preprocessor('install', inputs['projectenv'])
-    if inputs['projectenv'] is test.environment: # XXX
-        test.done_steps.add(STEP_INSTALLED)
-    return {}
-
-
-# checker actions ##############################################################
-
-act_pyunit = _make_test_runner_action('pyunit')
-act_pytest = _make_test_runner_action('pytest')
-
-
-@apycotlib.apycotaction('pylint', 'INSTALLED in elmt.done_steps')
-def act_pylint(inputs):
-    from apycotlib.checkers import python # trigger registration
-    test = inputs['apycot']
-    checker, status = test.run_checker('pylint', inputs.get('options'))
-    return {}
-
-
-@input('coverage.data', 'isinstance(elmt, FilePath)', 'elmt.type == "coverage.data"')
-@apycotlib.apycotaction('pycoverage')
-def act_pycoverage(inputs):
-    from apycotlib.checkers import python # trigger registration
-    test = inputs['apycot']
-    options = inputs.get('options') # from apycotaction
-    options['coverage.data'] = inputs['coverage.data'].path
-    checker, status = test.run_checker('pycoverage', options=options)
-    return {}
-
-
-@input('changes-files', 'isinstance(elmt, FilePath)', 'elmt.type == "debian.changes"',
-        list=True)
-@apycotlib.apycotaction('lintian', 'DEBIANPKG in elmt.done_steps')
-def act_lintian(inputs):
-    test = inputs['apycot']
-    options = inputs['options'].copy()
-    options['changes-files'] = inputs['changes-files']
-    checker, status = test.run_checker('lintian', options)
-    return {}
-
-class DebianLintianChecker(BaseChecker):
-    id = 'lintian'
-
-    checked_extensions = ('.changes',)
-    options_def = {
-        'changes-files': {
-            'type': 'csv',
-            'required': True,
-            'help': 'changes files to check',
-        },
-    }
-
-    def get_output(self, path):
-        cmd = subprocess.Popen(['lintian', '-I', '--suppress-tags', 'bad-distribution-in-changes-file', path],
-                               stdout=subprocess.PIPE, stdin=open('/dev/null'), stderr=subprocess.STDOUT)
-        for line in cmd.stdout:
-            yield line
-        cmd.wait()
-
-    def do_check(self, test):
-        status = apycotlib.SUCCESS
-        for f in self.options.get('changes-files'):
-            iter_line = self.get_output(f.path)
-            for line in iter_line:
-                line_parts = line.split(':', 1)
-                if len(line_parts) > 1:
-                    mtype, msg = line_parts
-                    if mtype == 'W':
-                        self.writer.warning(msg, path=f.path)
-                    elif mtype == 'E':
-                        self.writer.error(msg, path=f.path)
-                        status = apycotlib.FAILURE
-                    elif mtype == 'I':
-                        self.writer.info(msg, path=f.path)
-                    else:
-                        self.writer.info(msg, path=f.path)
-                else:
-                    self.writer.fatal('unexpected line %r' % line, path=f.path)
-                    for line in iter_line:
-                        self.writer.info('followed by: %r' % line, path=f.path)
-                    return apycotlib.ERROR
-        return status
-
-apycotlib.register('checker', DebianLintianChecker)
-
--- a/recipes.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/recipes.py	Tue Jul 23 15:12:25 2013 +0200
@@ -1,22 +1,27 @@
+#
+quick_script = u'''
+from apycotlib import narvalactions as na
+# `plan`
+
+with na.apycot_environment(plan) as test:
+    na.install_environment(test)
+    checker, status = test.run_checker('pyunit')
+'''
 def create_quick_recipe(session):
-    recipe = session.create_entity('Recipe', name=u'apycot.recipe.quick')
-    init = recipe.add_step(u'action', u'apycot.init', initial=True)
-    getdeps = init.add_next_step(u'action', u'apycot.get_dependencies')
-    checkout = getdeps.add_next_step(u'action', u'apycot.checkout', for_each=u'projectenv')
-    install = checkout.add_next_step(u'action', u'apycot.install', for_each=u'projectenv')
-    pyunit = install.add_next_step(u'action', u'apycot.pyunit', final=True)
+    recipe = session.create_entity('Recipe', name=u'apycot.recipe.quick',
+                                   script=quick_script)
+
+full_script = u'''
+from apycotlib import narvalactions as na
+# `plan`
 
+with na.apycot_environment(plan) as test:
+    na.install_environment(test)
+    checker, status = test.run_checker('pyunit', pycoverage=True)
+    checker, status = test.run_checker('pycoverage')
+    checker, status = test.run_checker('pylint')
+'''
 def create_full_recipe(session):
-    recipe = session.create_entity('Recipe', name=u'apycot.recipe.full')
-    init = recipe.add_step(u'action', u'apycot.init', initial=True)
-    getdeps = init.add_next_step(u'action', u'apycot.get_dependencies')
-    checkout = getdeps.add_next_step(u'action', u'apycot.checkout', for_each=u'projectenv')
-    install = checkout.add_next_step(u'action', u'apycot.install', for_each=u'projectenv')
-    pylint = recipe.add_step(u'action', u'apycot.pylint')
-    pyunit = recipe.add_step(u'action', u'apycot.pyunit',
-                             arguments=u'EnsureOptions(pycoverage=True)')
-    recipe.add_transition(install, (pylint, pyunit))
-    pycoverage = pyunit.add_next_step(u'action', u'apycot.pycoverage')
-    recipe.add_transition((pylint, pycoverage),
-                          recipe.add_step(u'action', u'basic.noop', final=True))
+    recipe = session.create_entity('Recipe', name=u'apycot.recipe.full',
+                                   script=full_script)
     return recipe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/data/project/__pkginfo__.py	Tue Jul 23 15:12:25 2013 +0200
@@ -0,0 +1,1 @@
+modname = distname = 'project'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/data/project/setup.py	Tue Jul 23 15:12:25 2013 +0200
@@ -0,0 +1,1 @@
+print 'hello'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_functional.py	Tue Jul 23 15:12:25 2013 +0200
@@ -0,0 +1,29 @@
+import os.path as osp
+import subprocess
+import shutil
+
+import utils
+
+HERE = osp.abspath(osp.dirname(__file__))
+def setUpModule():
+    subprocess.check_call(['hg', 'init', '-q', osp.join(HERE, 'data', 'project')])
+    subprocess.check_call(['hg', 'addremove', '-q', '-R', osp.join(HERE, 'data', 'project')])
+    subprocess.check_call(['hg', 'commit', '-q', '-R', osp.join(HERE, 'data', 'project'), '-m', 'ze rev'])
+
+def tearDownModule():
+    shutil.rmtree(osp.join(HERE, 'data', 'project', '.hg'))
+
+class ApycotTC(utils.ApycotBaseTC):
+
+    def test_quick_recipe(self):
+        te = self.lgc.start(self.lgce)
+        self.commit()
+        self.run_plan(te)
+        self.assertEqual(dict((checker.name, checker.status) for checker in te.checkers),
+                         {'pyunit': 'nodata'})
+
+        te = self.lgc.start(self.lgce)
+        self.commit()
+        self.run_plan(te)
+        self.assertEqual(dict((checker.name, checker.status) for checker in te.checkers),
+                         {'pyunit': 'nodata'})
--- a/test/unittest_entities.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/test/unittest_entities.py	Tue Jul 23 15:12:25 2013 +0200
@@ -33,7 +33,7 @@
                          {'DISPLAY': ':1.0', 'NO_SETUPTOOLS': '1'})
 
         self.assertEqual(self.lgd.apycot_configuration(self.lgce),
-                          {'install': 'setup_install',
+                          {'install': 'python_setup',
                            'python_lint_treshold': '7',
                            'python_lint_ignore': 'thirdparty',
                            'python_test_coverage_treshold': '70',
@@ -41,7 +41,7 @@
 
     def test_refinement_override(self):
         self.assertEqual(self.lgc.apycot_configuration(self.lgce),
-                          {'install': 'setup_install',
+                          {'install': 'python_setup',
                            'python_lint_treshold': '8',
                            'python_lint_ignore': 'thirdparty',
                            'python_test_coverage_treshold': '70',
--- a/test/unittest_task.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/test/unittest_task.py	Tue Jul 23 15:12:25 2013 +0200
@@ -43,15 +43,15 @@
         if exists(path):
             shutil.rmtree(path)
 
-def Test(tconfig, *args, **kwargs):
-    pps = kwargs.pop('preprocessors', None)
-    checkers = kwargs.pop('checkers', None)
-    repo = kwargs.pop('repo', MOCKREPO)
-    environment = kwargs.pop('environment',
-                             Environment(eid=tconfig.name, apycot_preprocessors={}))
+def Test(tconfig, writer, preprocessors=None, checkers=None,
+         repo=None, environment=None):
+    pps = preprocessors
+    repo = repo or MOCKREPO
+    environment = environment or Environment(eid=tconfig.name, apycot_preprocessors={})
     texec = mock_object(configuration=tconfig, environment=environment,
-                        branch=environment.conf.get('branch'))
-    test = BaseTest(texec, *args, **kwargs)
+                        branch=environment.conf.get('branch'),
+                        options_dict=lambda self:{})
+    test = BaseTest(texec, writer)
     if pps is not None:
         test.apycot_preprocessors = lambda x: pps
     if checkers is not None:
@@ -186,7 +186,7 @@
         self.skipTest('to be done by pyves')
         pp = SimplePreprocessor()
         test = Test(TestConfig('yo', dependencies=(Environment('pypasax'),)),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': pp})
         test._repositories['pypasax'] = SVNREPO2
@@ -197,7 +197,7 @@
     def test_setup_no_install(self):
         self.skipTest('to be done by pyves')
         test = Test(TestConfig('yo', dependencies=(Environment('pypasax'),)),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     preprocessors={'install': TPP})
         test._repositories['pypasax'] = SVNREPO2
         # no checks requiring installation, main repo should be checked out though not installed,
@@ -216,7 +216,7 @@
     def test_python_setup(self):
         self.skipTest('to be done by pyves')
         test = Test(TestConfig('yo', dependencies=(Environment('pypasax'),)),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': TPP})
         test._repositories['pypasax'] = SVNREPO2
@@ -254,19 +254,19 @@
     def test_setup_raise(self):
         self.skipTest('to be done by pyves')
         # test bad checkout command
-        test = Test(TestConfig('yo'), MockTestWriter(), {}, repo=BADREPO)
+        test = Test(TestConfig('yo'), MockTestWriter(), repo=BADREPO)
         self._test_setup_ex(test, "`false` returned with status : 1")
         # test bad dependencies checkout
         test = Test(TestConfig('yo', dependencies=(Environment('toto'),),
                                ),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()])
         test._repositories['toto'] = BADREPO
         self._test_setup_ex(test)
         # test bad preprocessing
         test = Test(TestConfig('yo', dependencies=(Environment('pypasax'),),
                                ),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': SetupRaisePreprocessor()})
         test._repositories['pypasax'] = SVNREPO2
@@ -276,7 +276,7 @@
         self.skipTest("We don't execute whole test anymore")
         test = Test(TestConfig('yo', dependencies=(Environment('pypasax'),),
                                ),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': TPP})
         test._repositories['pypasax'] = SVNREPO2
@@ -292,7 +292,7 @@
         self.skipTest("We don't execute whole test anymore")
         test = Test(TestConfig('yo', dependencies=(Environment('Pypasax'),),
                                ),
-                    MockTestWriter(), {}, repo=SVNREPO1,
+                    MockTestWriter(), repo=SVNREPO1,
                     checkers=[SuccessTestChecker(), FailureTestChecker(), ErrorTestChecker()],
                     preprocessors={'install': TPP})
         test._repositories['Pypasax'] = SVNREPO2
@@ -306,7 +306,7 @@
         self.skipTest("We don't execute whole test anymore")
         test = Test(TestConfig('yo', dependencies=(Environment('Pypasax', SVNREPO2),),
                                      ),
-                    MockTestWriter(), {}, repo=SVNREPO1,
+                    MockTestWriter(), repo=SVNREPO1,
                     checkers=[SuccessTestChecker(), FailureTestChecker(), ErrorTestChecker()],
                     preprocessors={'install:': SetupRaisePreprocessor()})
         test._repositories['Pypasax'] = SVNREPO2
@@ -317,7 +317,7 @@
         command = 'cp -R '+abspath('inputs/goodpkg')+' .'
         cwd = os.getcwd()
         test = Test(TestConfig('yo', dependencies=(Environment('Pypasax'),)),
-                    MockTestWriter(), {})
+                    MockTestWriter())
         test._repositories['Pypasax'] = SVNREPO2
         self.failUnless(exists(test.tmpdir))
         test.execute()
@@ -334,7 +334,7 @@
 
         test = Test(TestConfig('yo', dependencies=(Environment('Pypasax'),),
                                      ),
-                    MockTestWriter()(), {}, repo=SVNREPO1,
+                    MockTestWriter()(), repo=SVNREPO1,
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': SetupRaisePreprocessor()})
         test._repositories['Pypasax'] = SVNREPO2
@@ -345,7 +345,7 @@
 
         test = Test(TestConfig('yo', dependencies=(Environment('Pypasax'),),
                                      ),
-                    MockTestWriter()(), {}, repo=SVNREPO1,
+                    MockTestWriter()(), repo=SVNREPO1,
                     checkers=[SuccessTestChecker()],
                     preprocessors={'install': CleanRaisePreprocessor()})
         test._repositories['Pypasax'] = SVNREPO2
@@ -356,7 +356,7 @@
 
     def test_branch(self):
         test = Test(TestConfig('yo'),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     environment=Environment('babar', conf={'branch': 'bob'}),
                     checkers=[SuccessTestChecker()])
         del test._repositories['babar'] # XXX clean up this mess
@@ -366,7 +366,7 @@
     def test_branch_deps_with_branch(self):
         dep = Environment('babar', conf={'branch': 'Onk'})
         test = Test(TestConfig('yo', dependencies=(dep, )),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()])
         repo = test.apycot_repository(dep)
         self.assertEqual(repo.branch, 'Onk')
@@ -374,7 +374,7 @@
     def test_branch_deps_without_branch(self):
         dep = Environment('babar')
         test = Test(TestConfig('yo', dependencies=(dep, )),
-                    MockTestWriter(), {},
+                    MockTestWriter(),
                     checkers=[SuccessTestChecker()])
         repo = test.apycot_repository(dep)
         # default should be the branch name (as none is defined)
@@ -394,7 +394,7 @@
         self._PYTHONPATH = os.environ.get('PYTHONPATH', '')
         os.environ['PYTHONPATH'] = ''
         self.tracker = Test(TestConfig('yo', dependencies=(Environment('pypasax'),)),
-                            MockTestWriter(), {})
+                            MockTestWriter())
 
     def tearDown(self):
         os.environ['PYTHONPATH'] = self._PYTHONPATH
--- a/test/utils.py	Wed Aug 07 10:46:21 2013 +0200
+++ b/test/utils.py	Tue Jul 23 15:12:25 2013 +0200
@@ -127,31 +127,28 @@
     def commit(self):
         pass
 
+from cubes.narval.testutils import NarvalBaseTC
 
-class ApycotBaseTC(CubicWebTC):
+class ApycotBaseTC(NarvalBaseTC):
 
     def setup_database(self):
         req = self.request()
         self.lgce = req.create_entity(
             'ProjectEnvironment', name=u'lgce',
-            check_config=u'install=setup_install\nenv-option=value',
+            check_config=u'install=python_setup\nenv-option=value',
             check_environment=u'SETUPTOOLS=1\nDISPLAY=:2.0'
             )
         self.vcsrepo = req.create_entity('Repository', type=u'mercurial',
                                          # use path to avoid clone attempt when using url
-                                         path=u'/src/logilab/common',
+                                         path=unicode(self.datapath('project')),
                                          reverse_local_repository=self.lgce)
         self.pyp = req.create_entity('TestConfig', name=u'PYTHONPACKAGE',
                                      check_config=u'python_lint_treshold=7\n'
                                      'python_lint_ignore=thirdparty\n'
                                      'python_test_coverage_treshold=70\n',
                                      check_environment=u'NO_SETUPTOOLS=1\nDISPLAY=:1.0')
-        self.lgc = self.add_test_config(u'lgc', env=self.lgce, group=self.pyp)
-        self.recipe = req.create_entity('Recipe', name=u'functest.noop',
-                                        reverse_use_recipe=self.lgc)
-        step1 = self.recipe.add_step(u'action', u'basic.noop', initial=True)
-        step2 = self.recipe.add_step(u'action', u'basic.noop', final=True)
-        tr = self.recipe.add_transition(step1, step2)
+        self.recipe = req.execute('Recipe X WHERE X name "apycot.recipe.quick"').get_entity(0, 0)
+        self.lgc = self.add_test_config(u'lgc', env=self.lgce, group=self.pyp, use_recipe=self.recipe)
 
         self.repo.threaded_task = lambda func: func() # XXX move to cw