[CORD-3206]

- enable junit-xml output from nose2 unit tests
- Delete obsolete django-based tests
- cleanup of virtualenv scripts

Change-Id: Ibc014da4319bdc00f6cf321350389ac93ac46804
diff --git a/.gitignore b/.gitignore
index 5fd7997..2078903 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,10 +35,10 @@
 _book/
 .noseids
 
-lib/xos-config/cover/
-lib/xos-config/.coverage
-lib/xos-config/coverage.xml
+# testing/coverage files
+nose2-junit.xml
+.coverage
+coverage.xml
 
+lib/xos-config/cover/
 lib/xos-genx/cover/
-lib/xos-genx/.coverage
-lib/xos-genx/coverage.xml
diff --git a/docs/dev/local_env.md b/docs/dev/local_env.md
deleted file mode 100644
index af3b61e..0000000
--- a/docs/dev/local_env.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# How to setup a local dev environmnet
-
-As now this is useful for working on libraries and will give you access to the
-`xossh` cli tool.
-
-## Create a python virtual-env
-
-We are providing an helper script to setup a python virtual environment and
-install all the required dependencies, to use it:
-
-```bash
-source scripts/setup_venv.sh
-```
-
-At this point xos libraries are installed as python modules, so you can use any
-cli tool, for instance:
-
-```bash
-xossh
-```
-
-will open an xos shell to operate on models.  For more informations on `xossh`
-look at `xos/xos_client/README.md`
-
-> NOTE: The `xossh` tool accept parameters to be configured, for example to use
-> it against a local installation (frontend VM) you use:
->
-> ```bash
-> xossh -G 192.168.46.100:50055 -S 192.168.46.100:50051
-> ```
diff --git a/docs/dev/unittest.md b/docs/dev/unittest.md
index 3dd979a..e718f0c 100644
--- a/docs/dev/unittest.md
+++ b/docs/dev/unittest.md
@@ -5,28 +5,34 @@
 ## Setting up a unit testing environment
 
 To run unit tests, an environment needs to be setup with the appropriate python
-libraries used by the unit testing framework and by the XOS libraries that are
-being tested. One way to accomplish this is to setup a
-[virtual-env](local_env.md). You will also need to copy Chameleon from
-`component/chameleon` to `containers/xos/tmp.chameleon`. Here is a set of
-commands that may prove useful:
+libraries used by the unit testing framework and also the XOS libraries that
+are being tested. There is a development/test convenience script,
+`setup_venv.sh`, that sets up a python virtualenv and installs all the required
+packages to run local CLI tools.
 
-```shell
-brew install graphviz
-pip install --install-option="--include-path=/usr/local/include/" --install-option="--library-path=/usr/local/lib/" pygraphviz
-source scripts/setup_venv.sh
-pip install nose2 mock
-cp -R ../../component/chameleon containers/xos/tmp.chameleon
+Assuming you've checked out the whole source repository with `repo` into `~/cord`:
+
+```bash
+cd ~/cord/orchestration/xos
+./scripts/setup_venv.sh
+source venv-xos/bin/activate
 ```
 
+At this point all the XOS libraries are installed as python modules, so you can use any
+cli tool such as `xosgenx` or `xossh`, as well as the unit testing tools.
+
 ## Running unit tests
 
-To run unit tests, go to the root of the xos repository and run the following:
+To run unit tests, go to the root of the `xos` repository and run the following
+to run the tests and print a coverage report:
 
 ```shell
-nose2 --verbose --exclude-ignored-files
+nose2 --verbose --with-coverage --coverage-report term
 ```
 
+You can also run unit tests in a service repository by going into the `xos`
+subdirectory and running the same command.
+
 ## Writing new unit tests
 
 New test filename should start with the string `test`. For example,
@@ -36,7 +42,12 @@
 ## Ignoring unwanted unit tests
 
 Some tests are still being migrated to the unit testing framework and/or
-require features that may not be present in the virtual-env. Placing the string
-`# TEST_FRAMEWORK: IGNORE` anywhere in a python file will prevent it from being
-executed automatically by the test framework.
+require features that may not be present in the virtual-env. Placing the
+[__test__
+attribute](https://nose2.readthedocs.io/en/latest/plugins/dundertests.html) set to `False`:
 
+```python
+__test__ = False
+```
+
+in a class will exclude it from being evaluated by the test framework.
diff --git a/docs/dev/xosgenx.md b/docs/dev/xosgenx.md
index 88f8974..53e7374 100644
--- a/docs/dev/xosgenx.md
+++ b/docs/dev/xosgenx.md
@@ -94,9 +94,9 @@
 It is possible to run the xosgenx tool chain directly. This is useful, for
 example, when developing a new target.
 
-To do do, first setup the python virtual environment as described
-[here](local_env.md). Then drop an xproto file in your working directory. For
-example, you can copy-and-paste the following content into a file named
+To do do, first setup the python virtual environment as described in the [unit
+testing docs](unittest.md). Then drop an xproto file in your working directory.
+For example, you can copy-and-paste the following content into a file named
 `slice.xproto`:
 
 ```protobuf
diff --git a/nose2-plugins/__init__.py b/nose2-plugins/__init__.py
deleted file mode 100644
index 42722a8..0000000
--- a/nose2-plugins/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
diff --git a/nose2-plugins/exclude.py b/nose2-plugins/exclude.py
deleted file mode 100644
index 241eadb..0000000
--- a/nose2-plugins/exclude.py
+++ /dev/null
@@ -1,32 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import logging
-import os
-
-from nose2.events import Plugin
-
-log = logging.getLogger('nose2.plugins.excludeignoredfiles')
-
-class ExcludeIgnoredFiles(Plugin):
-    commandLineSwitch = (None, 'exclude-ignored-files', 'Exclude that which should be excluded')
-
-    def matchPath(self, event):
-        if event.path.endswith(".py"):
-            text = open(event.path, "r").read()
-            if "test_framework: ignore" in text.lower():
-                log.info("Ignoring %s" % event.path)
-                event.handled = True
-                return False
diff --git a/scripts/setup_venv.sh b/scripts/setup_venv.sh
index 73effb1..99717e1 100755
--- a/scripts/setup_venv.sh
+++ b/scripts/setup_venv.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # Copyright 2017-present Open Networking Foundation
 #
@@ -14,50 +14,46 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-BASEDIR=$(pwd)
-REQUIREMENTS=$BASEDIR/containers/xos/pip_requested.txt
-VENVDIR=venv-xos
+# setup_venv_lite.sh
+# sets up a python virtualenv for testing and service development
 
-echo $BASEDIR
-echo $REQUIREMENTS
-echo $VENVDIR
+set -e -o pipefail
+
+WORKSPACE=${WORKSPACE:-.}
+XOS_DIR=${XOS_DIR:-.}
+PIP_REQS=${PIP_REQS:-${XOS_DIR}/scripts/xos_dev_reqs.txt}
+VENVDIR="${WORKSPACE}/venv-xos"
 
 # create venv if it's not yet there
-if [ ! -d "$BASEDIR/$VENVDIR" ]; then
-   echo "Setting up virtualenv for XOS"
-   virtualenv -q $BASEDIR/$VENVDIR --no-site-packages
-   pip install --upgrade pip
-   echo "Virtualenv created."
+if [ ! -x "${VENVDIR}/bin/activate" ]; then
+  echo "Setting up dev/test virtualenv in ${VENVDIR} for XOS"
+  virtualenv -q "${VENVDIR}" --no-site-packages
+  echo "Virtualenv created."
 fi
 
-# activate the virtual env
-if [ ! $VIRTUAL_ENV ]; then
-   source $BASEDIR/$VENVDIR/bin/activate
-   echo "Virtualenv activated."
-fi
+echo "Installing python requirements in virtualenv with pip"
+source "${VENVDIR}/bin/activate"
+pip install --upgrade pip
+pip install -r "$PIP_REQS"
 
-# install pip requirements
-if \
-pip install cryptography --global-option=build_ext --global-option="-L/usr/local/opt/openssl/lib" --global-option="-I/usr/local/opt/openssl/include" && \
-pip install -r $REQUIREMENTS && \
-cd $BASEDIR/lib/xos-config; python setup.py install && \
+pushd "$XOS_DIR/lib/xos-util"
+python setup.py install
+echo "xos-util Installed"
+popd
 
-#install xos-client
-cp -R $BASEDIR/containers/xos/tmp.chameleon $BASEDIR/xos/xos_client/xosapi/chameleon && \
-cd $BASEDIR/xos/xos_client/xosapi/chameleon/protos; VOLTHA_BASE=anything make && \
-cd $BASEDIR/xos/xos_client; python setup.py install && \
-chmod 777 $BASEDIR/venv-xos/lib/python2.7/site-packages/xosapi/chameleon/protoc_plugins/gw_gen.py && \
-chmod 777 $BASEDIR/venv-xos/lib/python2.7/site-packages/xosapi/chameleon/protoc_plugins/swagger_gen.py && \
+pushd "$XOS_DIR/lib/xos-config"
+python setup.py install
+echo "xos-config Installed"
+popd
 
-#install xos-genx
-cd $BASEDIR/lib/xos-genx; python setup.py install && \
+pushd "$XOS_DIR//lib/xos-genx"
+python setup.py install
+echo "xos-genx Installed"
+popd
 
-#install xos-util
-cd $BASEDIR/lib/xos-util; python setup.py install
- then
-   echo "Requirements installed."
-   echo "Virtualenv ready"
- else
-   echo "An error occurred"
-fi
-cd $BASEDIR
+pushd "$XOS_DIR/xos/xos_client"
+make
+echo "xos-client Installed"
+popd
+
+echo "XOS dev/test virtualenv created. Run 'source ${VENVDIR}/bin/activate'."
diff --git a/scripts/setup_venv_lite.sh b/scripts/setup_venv_lite.sh
deleted file mode 100755
index 82ba642..0000000
--- a/scripts/setup_venv_lite.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# setup_venv_lite.sh
-# sets up a python virtualenv for testing and service development
-
-set -eu -o pipefail
-
-BASEDIR=$(pwd)
-REQUIREMENTS=$BASEDIR/scripts/xos_reqs_lite.txt
-VENVDIR=venv-xos-lite
-
-# create venv if it's not yet there
-if [ ! -x "$BASEDIR/$VENVDIR/bin/activate" ]; then
-  echo "Setting up virtualenv ${BASEDIR}/${VENVDIR} for XOS"
-  virtualenv -q "$BASEDIR/$VENVDIR" --no-site-packages
-  pip install --upgrade pip
-  echo "Virtualenv created."
-fi
-
-set +u
-# activate the virtual env
-if [ ! -x "$VIRTUAL_ENV" ]; then
-  source "$BASEDIR/$VENVDIR/bin/activate"
-  echo "Virtualenv activated."
-fi
-
-pip install -r "$REQUIREMENTS"
-cd "$BASEDIR/lib/xos-config"; python setup.py install
-cd "$BASEDIR/lib/xos-genx"; python setup.py install
-cd "$BASEDIR/lib/xos-util"; python setup.py install
-
diff --git a/scripts/xos_reqs_lite.txt b/scripts/xos_dev_reqs.txt
similarity index 94%
rename from scripts/xos_reqs_lite.txt
rename to scripts/xos_dev_reqs.txt
index 2d453d5..1680477 100644
--- a/scripts/xos_reqs_lite.txt
+++ b/scripts/xos_dev_reqs.txt
@@ -1,6 +1,7 @@
 Jinja2==2.10
 Pattern==2.6
 PyYAML==3.12
+Twisted==16.6.0
 astunparse==1.5.0
 colorama==0.3.9
 grpcio-tools==1.12.0
diff --git a/unittest.cfg b/unittest.cfg
index 6050396..f37d783 100644
--- a/unittest.cfg
+++ b/unittest.cfg
@@ -1,5 +1,7 @@
 [unittest]
-plugins=nose2-plugins.exclude
+plugins=nose2.plugins.junitxml
+
 code-directories=xos-genx
                  xos-config
                  coreapi
+
diff --git a/xos/core/tests.py b/xos/core/tests.py
deleted file mode 100644
index 2c115e0..0000000
--- a/xos/core/tests.py
+++ /dev/null
@@ -1,354 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# TEST_FRAMEWORK: IGNORE
-
-# TEST
-# To execute these tests use `python manage.py test core`
-
-#!/usr/bin/env python
-from django.test import TestCase
-from django.contrib.auth.models import User
-from rest_framework import status
-from rest_framework.test import APIClient
-from rest_framework.test import APITestCase
-import json
-from django.forms.models import model_to_dict
-
-from core.models import *
-
-print "-------------------------- Let's test!!!!!!!! --------------------------"
-
-from django.apps import apps
-from django.test.client import Client
-from django.test import testcases
-from django.http import SimpleCookie, HttpRequest, QueryDict
-from importlib import import_module
-from django.conf import settings
-class FixedClient(Client):
-    def login(self, **credentials):
-        """
-        Sets the Factory to appear as if it has successfully logged into a site.
-
-        Returns True if login is possible; False if the provided credentials
-        are incorrect, or the user is inactive, or if the sessions framework is
-        not available.
-        """
-        from django.contrib.auth import authenticate, login
-        user = authenticate(**credentials)
-        if (user and user.is_active and
-                apps.is_installed('django.contrib.sessions')):
-            engine = import_module(settings.SESSION_ENGINE)
-
-            # Create a fake request to store login details.
-            request = HttpRequest()
-
-            # XOS's admin.py requires these to be filled in
-            request.POST = {"username": credentials["username"],
-                            "password": credentials["password"]}
-
-            if self.session:
-                request.session = self.session
-            else:
-                request.session = engine.SessionStore()
-            login(request, user)
-
-            # Save the session values.
-            request.session.save()
-
-            # Set the cookie to represent the session.
-            session_cookie = settings.SESSION_COOKIE_NAME
-            self.cookies[session_cookie] = request.session.session_key
-            cookie_data = {
-                'max-age': None,
-                'path': '/',
-                'domain': settings.SESSION_COOKIE_DOMAIN,
-                'secure': settings.SESSION_COOKIE_SECURE or None,
-                'expires': None,
-                }
-            self.cookies[session_cookie].update(cookie_data)
-
-            return True
-        else:
-            return False
-
-class FixedAPITestCase(testcases.TestCase):
-    client_class = FixedClient
-
-# Environment Tests - Should pass everytime, if not something in the config is broken.
-class SimpleTest(TestCase):
-    fixtures = []
-
-    def test_basic_addition(self):
-        """
-        Tests that 1 + 1 always equals 2.
-        """
-        self.assertEqual(1 + 1, 2)
-
-
-# Site Test
-class SiteTest(TestCase):
-    fixtures = []
-
-    def setUp(self):
-        Site.objects.create(
-            name="Test Site",
-            login_base="test_"
-        )
-
-    def test_read_site(self):
-        """
-        Should read a site in the DB.
-        """
-        site = Site.objects.get(name="Test Site")
-        # print(site._meta.get_all_field_names())
-        self.assertEqual(site.login_base, "test_")
-
-
-class UnautheticatedRequest(FixedAPITestCase):
-    fixtures = []
-
-    def test_require_authentication(self):
-        """
-        Ensure that request must be authenticated
-        """
-        response = self.client.get('/xos/sites/', format='json')
-        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
-
-
-class SiteTestAPI(FixedAPITestCase):
-    fixtures = []
-
-    def setUp(self):
-        self.site = Site.objects.create(
-            name="Test Site",
-            login_base="test_"
-        )
-        self.user = User(
-            username='testuser',
-            email='test@mail.org',
-            password='testing',
-            site=self.site,
-            is_admin=True
-        )
-        self.user.save()
-        self.client.login(username='test@mail.org', password='testing')
-
-    def test_read_site_API(self):
-        """
-        Read a Site trough API
-        """
-        response = self.client.get('/xos/sites/', format='json')
-        parsed = json.loads(response.content)
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        self.assertEqual(len(parsed), 1)
-        self.assertEqual(parsed[0]['login_base'], 'test_')
-
-    def test_create_site_API(self):
-        """
-        Create a Site trough API
-        """
-        data = {
-            'name': "Another Test Site",
-            'login_base': "another_test_",
-            'location': [10, 20],
-            'abbreviated_name': 'test'
-        }
-        response = self.client.post('/xos/sites/', data, format='json')
-        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
-        self.assertEqual(Site.objects.count(), 2)
-        self.assertEqual(Site.objects.filter(name="Another Test Site").count(), 1)
-
-
-class SliceTestAPI(FixedAPITestCase):
-    fixtures = []
-
-    def setUp(self):
-        self.site = Site.objects.create(
-            name="Test Site",
-            login_base="test_"
-        )
-        self.pi = SiteRole.objects.create(role='pi')
-        self.user = User(
-            username='testuser',
-            email='test@mail.org',
-            password='testing',
-            site=self.site
-        )
-        self.user.save()
-        self.siteprivileges = SitePrivilege.objects.create(
-            user=self.user,
-            site=self.site,
-            role=self.pi
-        )
-        self.serviceClass = ServiceClass.objects.create(
-            name='Test Service Class'
-        )
-        self.client.login(username='test@mail.org', password='testing')
-
-    def test_create_site_slice(self):
-        """
-        Add a slice to a given site
-        """
-        data = {
-            'name': "test_slice",
-            'site': self.site.id,
-            'serviceClass': self.serviceClass.id
-        }
-        response = self.client.post('/xos/slices/?no_hyperlinks=1', data, format='json')
-        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
-
-    def test_validation_slice_name(self):
-        """
-        The slice name should start with site.login_base
-        curl -H "Accept: application/json; indent=4" -u padmin@vicci.org:letmein 'http://xos:9999/xos/slices/?no_hyperlinks=1' -H "Content-Type: application/json" -X POST --data '{"name": "test", "site":"1", "serviceClass":1}'
-        """
-        data = {
-            'name': "wrong_slice",
-            'site': self.site.id,
-            'serviceClass': self.serviceClass.id
-        }
-        response = self.client.post('/xos/slices/?no_hyperlinks=1', data, format='json')
-        parsed = json.loads(response.content)
-        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
-        self.assertEqual(parsed['detail']['specific_error'], "slice name must begin with test_")
-
-    def test_only_admin_can_change_creator(self):
-        """
-        Only an admin can change the creator of a slice
-        """
-        slice = Slice.objects.create(
-            name="test_slice",
-            site=self.site,
-            serviceClass=self.serviceClass,
-            creator=self.user
-        )
-
-        user2 = User(
-            username='another_testuser',
-            email='another_test@mail.org',
-            password='testing',
-            site=self.site
-        )
-        user2.save()
-
-        data = model_to_dict(slice)
-        data['creator'] = user2.id
-        json_data = json.dumps(data)
-
-        response = self.client.put('/xos/slices/%s/?no_hyperlinks=1' % slice.id, json_data, format='json', content_type="application/json")
-        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
-        parsed = json.loads(response.content)
-        self.assertEqual(parsed['detail']['specific_error'], "Insufficient privileges to change slice creator")
-
-class ServiceTestAPI(FixedAPITestCase):
-    fixtures = []
-
-    def setUp(self):
-        self.site = Site.objects.create(
-            name="Test Site",
-            login_base="test_"
-        )
-        self.admin = User(
-            username='testadmin',
-            email='admin@mail.org',
-            password='testing',
-            site=self.site,
-            is_admin=True
-        )
-        self.admin.save()
-
-        self.user = User(
-            username='testuser',
-            email='user@mail.org',
-            password='testing',
-            site=self.site
-        )
-        self.user.save()
-
-        self.service1 = Service.objects.create(
-            name="fakeService1",
-            versionNumber="1.0.0",
-            published=True,
-            enabled=True
-        )
-
-        self.service2 = Service.objects.create(
-            name="fakeService1",
-            versionNumber="1.0.0",
-            published=True,
-            enabled=True
-        )
-
-        self.service_role = ServiceRole.objects.create(role='admin')
-
-        self.service_privileges = ServicePrivilege.objects.create(
-            user=self.user,
-            service=self.service2,
-            role=self.service_role
-        )
-
-    # TODO
-    # [x] admin view all service
-    # [ ] user view only service2
-    # [x] admin view a specific service service
-    # [ ] user view can't view a specific service
-    # [ ] user update service2
-    # [ ] usercan NOT update service2
-    # [x] admin update service1
-    def test_admin_read_all_service(self):
-        """
-        Admin should read all the services
-        """
-        self.client.login(username='admin@mail.org', password='testing')
-        response = self.client.get('/xos/services/', format='json')
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        self.assertEqual(len(json.loads(response.content)), 2)
-
-    # need to understand how slices are related
-    def xtest_user_read_all_service(self):
-        """
-        User should read only service for which have privileges
-        """
-        self.client.login(username='user@mail.org', password='testing')
-        response = self.client.get('/xos/services/', format='json')
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        self.assertEqual(len(json.loads(response.content)), 1)
-
-    def test_admin_read_one_service(self):
-        """
-        Read a given service
-        """
-        self.client.login(username='admin@mail.org', password='testing')
-        response = self.client.get('/xos/services/%s/' % self.service1.id, format='json')
-        parsed = json.loads(response.content)
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        self.assertEqual(parsed['name'], self.service1.name)
-
-    def test_admin_update_service(self):
-        """
-        Update a given service
-        """
-        data = model_to_dict(self.service1)
-        data['name'] = "newName"
-        json_data = json.dumps(data)
-
-        self.client.login(username='admin@mail.org', password='testing')
-        response = self.client.put('/xos/services/%s/' % self.service1.id, json_data, format='json', content_type="application/json")
-        parsed = json.loads(response.content)
-        self.assertEqual(response.status_code, status.HTTP_200_OK)
-        model = Service.objects.get(id=self.service1.id)
-        self.assertEqual(model.name, data['name'])
-        
diff --git a/xos/synchronizers/new_base/tests/test_controller_dependencies.py b/xos/synchronizers/new_base/tests/test_controller_dependencies.py
index 3ebf3d4..35bbdc8 100644
--- a/xos/synchronizers/new_base/tests/test_controller_dependencies.py
+++ b/xos/synchronizers/new_base/tests/test_controller_dependencies.py
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# TEST_FRAMEWORK: IGNORE
-
 import unittest
 from mock import patch
 import mock
@@ -27,6 +25,9 @@
 xos_dir = os.path.join(test_path, '..', '..', '..')
 
 class TestControllerDependencies(unittest.TestCase):
+
+    __test__ = False
+
     def setUp(self):
         global mock_enumerator, event_loop
 
diff --git a/xos/synchronizers/new_base/tests/test_scheduler.py b/xos/synchronizers/new_base/tests/test_scheduler.py
index 3e7119c..d8a7a7f 100644
--- a/xos/synchronizers/new_base/tests/test_scheduler.py
+++ b/xos/synchronizers/new_base/tests/test_scheduler.py
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# TEST_FRAMEWORK: IGNORE
-
 import unittest
 from mock import patch
 import mock
@@ -27,6 +25,9 @@
 xos_dir = os.path.join(test_path, '..', '..', '..')
 
 class TestScheduling(unittest.TestCase):
+
+    __test__ = False
+
     def setUp(self):
         global mock_enumerator, event_loop
 
diff --git a/xos/xos/tests.py b/xos/xos/tests.py
deleted file mode 100644
index c708c0a..0000000
--- a/xos/xos/tests.py
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# Copyright 2017-present Open Networking Foundation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# TEST_FRAMEWORK: IGNORE
-
-"""
-This file demonstrates writing tests using the unittest module. These will pass
-when you run "manage.py test".
-
-Replace this with more appropriate tests for your application.
-"""
-
-from django.test import TestCase
-
-
-class SimpleTest(TestCase):
-    def test_basic_addition(self):
-        """
-        Tests that 1 + 1 always equals 2.
-        """
-        self.assertEqual(1 + 1, 2)
diff --git a/xos/xos_client/Makefile b/xos/xos_client/Makefile
index f018a65..dcf7eac 100644
--- a/xos/xos_client/Makefile
+++ b/xos/xos_client/Makefile
@@ -1,6 +1,10 @@
 all: chameleon_protos xosapi_install
 
-chameleon_protos:
+xosapi/chameleon:
+	cd xosapi ;\
+	ln -s ../../../../../component/chameleon chameleon
+
+chameleon_protos: | xosapi/chameleon
 	cd xosapi/chameleon/protos; VOLTHA_BASE=anything make
 
 xosapi_install: