Test update command with --delete-old option

Add simple test to ensure the update command results in update_job()
being called as expected and a complex scenario to test that when only
some jobs are updated, that passing --delete-old option to update will
only remove those managed jobs no longer listed and cannot include jobs
that were skipped previously.

Additionally this has been tested with the problem commit for adding
parallel thread usage and after adjusting the names of the functions
mocked to align with the rename demonstrated the bug encountered by
applying commit 7100a7f225.

Change-Id: I9c8a0bf86be2e67e012a3cf2a46530fd2622712b
This commit is contained in:
Darragh Bailey 2015-05-08 21:07:23 +01:00 committed by Darragh Bailey
parent 6c6370bbff
commit 5b16aa9c55
2 changed files with 105 additions and 7 deletions

View File

@ -0,0 +1,101 @@
# Joint copyright:
# - Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# 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 os
from jenkins_jobs import cmd
from jenkins_jobs import builder
from tests.base import mock
from tests.cmd.test_cmd import CmdTestsBase
@mock.patch('jenkins_jobs.builder.Jenkins.get_plugins_info', mock.MagicMock)
class UpdateTests(CmdTestsBase):
@mock.patch('jenkins_jobs.cmd.Builder.update_job')
def test_update_jobs(self, update_job_mock):
"""
Test update_job is called
"""
# don't care about the value returned here
update_job_mock.return_value = ([], 0)
path = os.path.join(self.fixtures_path, 'cmd-002.yaml')
args = self.parser.parse_args(['update', path])
cmd.execute(args, self.config)
update_job_mock.assert_called_with([path], [])
@mock.patch('jenkins_jobs.builder.Jenkins.is_job', return_value=True)
@mock.patch('jenkins_jobs.builder.Jenkins.get_jobs')
@mock.patch('jenkins_jobs.builder.Builder.delete_job')
@mock.patch('jenkins_jobs.cmd.Builder')
def test_update_jobs_and_delete_old(self, builder_mock, delete_job_mock,
get_jobs_mock, is_job_mock):
"""
Test update behaviour with --delete-old option
Test update of jobs with the --delete-old option enabled, where only
some jobs result in has_changed() to limit the number of times
update_job is called, and have the get_jobs() method return additional
jobs not in the input yaml to test that the code in cmd will call
delete_job() after update_job() when '--delete-old' is set but only
for the extra jobs.
"""
# set up some test data
jobs = ['old_job001', 'old_job002']
extra_jobs = [{'name': name} for name in jobs]
builder_obj = builder.Builder('http://jenkins.example.com',
'doesnot', 'matter',
plugins_list={})
# get the instance created by mock and redirect some of the method
# mocks to call real methods on a the above test object.
b_inst = builder_mock.return_value
b_inst.plugins_list = builder_obj.plugins_list
b_inst.update_job.side_effect = builder_obj.update_job
b_inst.delete_old_managed.side_effect = builder_obj.delete_old_managed
def _get_jobs():
return builder_obj.parser.jobs + extra_jobs
get_jobs_mock.side_effect = _get_jobs
# override cache to ensure Jenkins.update_job called a limited number
# of times
self.cache_mock.return_value.has_changed.side_effect = (
[True] * 2 + [False] * 2)
path = os.path.join(self.fixtures_path, 'cmd-002.yaml')
args = self.parser.parse_args(['update', '--delete-old', path])
with mock.patch('jenkins_jobs.builder.Jenkins.update_job') as update:
with mock.patch('jenkins_jobs.builder.Jenkins.is_managed',
return_value=True):
cmd.execute(args, self.config)
self.assertEquals(2, update.call_count,
"Expected Jenkins.update_job to be called '%d' "
"times, got '%d' calls instead.\n"
"Called with: %s" % (2, update.call_count,
update.mock_calls))
calls = [mock.call(name) for name in jobs]
self.assertEquals(2, delete_job_mock.call_count,
"Expected Jenkins.delete_job to be called '%d' "
"times got '%d' calls instead.\n"
"Called with: %s" % (2, delete_job_mock.call_count,
delete_job_mock.mock_calls))
delete_job_mock.assert_has_calls(calls, any_order=True)

View File

@ -18,17 +18,14 @@ class CmdTestsBase(testtools.TestCase):
# are run in parallel. Stub out the CacheStorage to ensure that each
# test can safely create the cache directory without risk of
# interference.
self.cache_patch = mock.patch('jenkins_jobs.builder.CacheStorage',
autospec=True)
self.cache_patch.start()
cache_patch = mock.patch('jenkins_jobs.builder.CacheStorage',
autospec=True)
self.cache_mock = cache_patch.start()
self.addCleanup(cache_patch.stop)
self.config = configparser.ConfigParser()
self.config.readfp(StringIO(cmd.DEFAULT_CONF))
def tearDown(self):
self.cache_patch.stop()
super(CmdTestsBase, self).tearDown()
class CmdTests(CmdTestsBase):