Commit ebf7518d authored by Elisabetta Giani's avatar Elisabetta Giani
Browse files

CT-69: Implementing acceptance tests in TDD aprooach (first step)

parent 1e79f1c8
Loading
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -2359,9 +2359,6 @@ class CspSubarray(SKASubarray):
        # sub-array sub-component                
        # PROTECTED REGION END #    //  CspSubarray.GoToIdle
        
    @command(
    )
        
    @AdminModeCheck('Abort')
    def is_Abort_allowed(self):
        return self._is_subarray_configuring_allowed()
+91 −0
Original line number Diff line number Diff line
#
# Project makefile for a Tango project. You should normally only need to modify
# DOCKER_REGISTRY_USER and PROJECT below.
#

#
# DOCKER_REGISTRY_HOST, DOCKER_REGISTRY_USER and PROJECT are combined to define
# the Docker tag for this project. The definition below inherits the standard
# value for DOCKER_REGISTRY_HOST (=rnexus.engageska-portugal.pt) and overwrites
# DOCKER_REGISTRY_USER and PROJECT to give a final Docker tag of
# nexus.engageska-portugal.pt/tango-example/csplmc
#

DOCKER_REGISTRY_USER:=ska-docker
PROJECT = mid-csp-lmc

#
# include makefile to pick up the standard Make targets, e.g., 'make build'
# build, 'make push' docker push procedure, etc. The other Make targets
# ('make interactive', 'make test', etc.) are defined in this file.
#
include .make/Makefile.mk

#
# IMAGE_TO_TEST defines the tag of the Docker image to test
#
IMAGE_TO_TEST = $(DOCKER_REGISTRY_HOST)/$(DOCKER_REGISTRY_USER)/$(PROJECT):latest
#IMAGE_TO_TEST ?= nexus.engageska-portugal.pt/ska-docker/tango-vscode:0.2.4	

#
# CACHE_VOLUME is the name of the Docker volume used to cache eggs and wheels
# used during the test procedure. The volume is not used during the build
# procedure
#
CACHE_VOLUME = $(PROJECT)-test-cache

# optional docker run-time arguments
DOCKER_RUN_ARGS =

#
# Never use the network=host mode when running CI jobs, and add extra
# distinguishing identifiers to the network name and container names to
# prevent collisions with jobs from the same project running at the same
# time.
#
ifneq ($(CI_JOB_ID),)
NETWORK_MODE := tangonet-$(CI_JOB_ID)
CONTAINER_NAME_PREFIX := $(PROJECT)-$(CI_JOB_ID)-
else
CONTAINER_NAME_PREFIX := $(PROJECT)-
NETWORK_MODE := host
endif

#
# When running in network=host mode, point devices at a port on the host
# machine rather than at the container.
#
ifeq ($(NETWORK_MODE),host)
TANGO_HOST := $(shell hostname):10000
MYSQL_HOST := $(shell hostname):3306
else
# distinguish the bridge network from others by adding the project name
NETWORK_MODE := $(NETWORK_MODE)-$(PROJECT)
TANGO_HOST := $(CONTAINER_NAME_PREFIX)databaseds:10000
MYSQL_HOST := $(CONTAINER_NAME_PREFIX)tangodb:3306
endif

# here we copy the content of the acceptance_tests directory into the
# container running the test and then we run the requested make target
# into the container.
# In particular the directory is copied on itself so that we don't need to 
# re-run all the containers if something change in the test source code.
make = tar -c ../tests/acceptance_tests | \
	   docker run -i --rm --network=$(NETWORK_MODE) \
	   -e TANGO_HOST=$(TANGO_HOST) \
	   -v /build -w /build -u tango --name midcsp-tester $(IMAGE_TO_TEST) \
	   bash -c "sudo chown -R tango:tango /build && tar xv --directory /app/tests --strip-components 1 --warning=all && \
	   cd /app/tests/acceptance_tests  && make TANGO_HOST=$(TANGO_HOST) $1"

test: DOCKER_RUN_ARGS = --volumes-from=$(BUILD)
test: ## test the application
	$(call make,test); \
	  status=$$?; \
	  rm -fr build; \
	  docker cp $(BUILD):/build .; \
	  docker rm -f -v $(BUILD); \
	  exit $$status

# http://cakoose.com/wiki/gnu_make_thunks
BUILD_GEN = $(shell docker create -v /build $(IMAGE_TO_TEST))
BUILD = $(eval BUILD := $(BUILD_GEN))$(BUILD)
+18 −0
Original line number Diff line number Diff line
# Use bash shell with pipefail option enabled so that the return status of a
# piped command is the value of the last (rightmost) commnand to exit with a
# non-zero status. This lets us pipe output into tee but still exit on test
# failures.
SHELL = /bin/bash
.SHELLFLAGS = -o pipefail -c

all: test

test: install
	mkdir -p /build/reports && \
	pytest --no-cov --disable-pytest-warnings MidCspSubarrayConfiguration_test.py| tee out-stdout; \
	status=$$?; \
	exit $$status
	
install:
	pip3 install -r test_requirements.txt
.PHONY: test
+169 −0
Original line number Diff line number Diff line
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# This file is part of the csp-lmc project
#
#
#
# Distributed under the terms of the BSD-3-Clause license.
# See LICENSE.txt for more info.
"""Tests for ADR-4 and ADR-10 implementation into CSP.LMC Subarray."""

# Standard imports
import sys
import os
import time
import logging

# Tango imports
import tango
from tango import DevState, EventType
import pytest
import unittest

#Local imports
from ska.base.control_model  import ObsState

# TODO: remove call to sleep 

# Device test case
@pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_subarray01")

class TestBase(unittest.TestCase):
    fixture_names = ()
    @pytest.fixture(autouse=True)
    def auto_injector_fixture(self, request):
        names = self.fixture_names
        for name in names:
            setattr(self, name, request.getfixturevalue(name))

class TestCspSubarrayConfiguration(TestBase):
    fixture_names =("midcsp_master", "midcsp_subarray01", "cbf_subarray01")

    def __is_csp_subarray_off(self):
        #state = midcsp_subarray01.State()
        state = self.midcsp_subarray01.State()
        if state == DevState.OFF:
            return True
        return False

    #def __set_csp_subarray_to_off(self,midcsp_subarray01):
    def __set_csp_subarray_to_off(self):
        if not self.__is_csp_subarray_off():
            self.midcsp_subarray01.RemoveAllReceptors()
            time.sleep(3)
            state = self.midcsp_subarray01.State()
            if state == DevState.OFF:
                return True
            return False

    def __set_csp_subarray_to_on(self):
        """
        Set the CSP Subarray to ON state.
        """
        # check if the subarray is in OFF-IDLE state
        if self.__is_csp_subarray_off():
            # read from the CSP Master the list of available receptors
            unassigned_receptors = self.midcsp_master.unassignedReceptorIDs
            # assign the first one to the subarray
            self.midcsp_subarray01.AddReceptors([unassigned_receptors[0],])
            # wait for the transition of the CSP subarray to ON
            time.sleep(3)
            # check the final subarray state
            state = self.midcsp_subarray01.State()
            if state == DevState.ON:
                return True
            return False

    def test_happy_path(self):
        """
        Test the happy path
        """
        # setup the CSP Subarray
        state = self.midcsp_subarray01.State()
        assert state in [DevState.DISABLE]
        #switch-on the CspMaster
        self.midcsp_master.On("")
        # wait for transition to OFF
        time.sleep(2)
        state = self.midcsp_subarray01.State()
        assert state in [DevState.OFF]
        self.__set_csp_subarray_to_on()
        # load the json script from a file
        json_file = open("test_ConfigureScan_ADR4.json")
        # exercise the device
        self.midcsp_subarray01.Configure(json_file.read().replace("\n", ""))
        time.sleep(3)

        # check
        # The CSP Subarray ObsState is READY
        obs_state = self.midcsp_subarray01.obsState
        assert obs_state == ObsState.READY
        
        # reset the device to initial state
        self.midcsp_subarray01.RemoveAllReceptors()
        time.sleep(3)
        self.midcsp_master.Standby("")
        time.sleep(3)
        state = self.midcsp_subarray01.State()
        assert state == DevState.DISABLE

    def test_json_without_configuration_id(self):
        """
        Configure the CSP Subarray sending a json configuration script 
        without the configID entry. 
        """
        # setup the test
        # Set the CSP Subarray to ON-IDLE state
        if not self.__set_csp_subarray_to_on():
            assert 0
        obs_state = self.midcsp_subarray01.obsState
        assert obs_state == ObsState.IDLE
        # load the json configuration from a file
        json_file = open("test_ConfigureScan_without_configID.json")

        # exercise the device
        with pytest.raises(tango.DevFailed) as df:

            self.midcsp_subarray01.Configure(json_file.read().replace("\n", ""))
        if df:
            err_msg = str(df.value.args[0].desc)
            assert "No configID in json script" in err_msg
        # check
        # read the Subarray State and ObsState and check against
        # ON-IDLE
        # maybe we need only to check the obsState (?)
        state = self.midcsp_subarray01.State()
        assert state == DevState.ON
        obs_state = self.midcsp_subarray01.obsState
        assert obs_state == ObsState.IDLE

    def test_cspsubarray_wrong_state_for_configure(self):
        """
        Set the CSP Subarray in a wrong state and issue the
        Configure command on it
        """
        # setup the test 
        if not self.__set_csp_subarray_to_off():
            #state = self.midcsp_subarray01.State()
            #assert state == DevState.OFF
            assert 0
        obs_state = self.midcsp_subarray01.obsState
        assert obs_state == ObsState.IDLE
        # the State-obsState value is OFF-IDLE. Wrong state to issue
        # configuration

        # load the json file
        json_file = open("test_ConfigureScan_ADR4.json")

        # exercise the device
        # Issue the Configure command
        with pytest.raises(tango.DevFailed) as df:
            self.midcsp_subarray01.Configure(json_file.read().replace("\n", ""))
        if df:
            err_msg = str(df.value.args[0].desc)
            assert "Command Configure not allowed" in err_msg
        # check
        # Subarray final ObsState IDLE
        obs_state = self.midcsp_subarray01.obsState
        assert obs_state == ObsState.IDLE
+5 −0
Original line number Diff line number Diff line
pytest-json-report
pycodestyle
pytest-ordering
importlib
mock