System Tests - Switch from robot to nosetests

This patch updates the System tests to use nosetests,
in place Robot framework.

blueprint system-tests
Change-Id: I4c51cb042ab21e2796b55fb13d69ae3afa2af172
This commit is contained in:
Malini Kamalambal 2013-06-24 12:21:13 -04:00
parent a262a658d3
commit e411ff9b9f
21 changed files with 810 additions and 604 deletions

View File

@ -13,8 +13,8 @@ Running the System Tests
#. Setup a Marconi server. Refer to the Marconi `README`_ on
how to run Marconi locally, or simply use an existing server.
#. System tests require the `requests`_ & `robot`_ packages. Run
the following to install them: ::
#. System tests require the `requests` package. Run
the following to install it: ::
pip install -r tools/system-test-requires
@ -31,35 +31,21 @@ Running the System Tests
#. If leaving keystone auth enabled, update system-tests.conf with a
valid set of credentials.
#. Now, to run the sytem tests, simply use the pybot commands, e.g.:
#. Now, to run the sytem tests, simply use the nosetests commands,
from the marconi/tests/system directory. e.g.:
Run all test suites: ::
pybot queue/queue_tests.txt messages/messages_tests.txt claim/claim_tests.txt
Run test suites individually: ::
pybot queue/queue_tests.txt
pybot messages/messages_tests.txt
pybot claim/claim_tests.txt
Note: pybot will generate ``report.html`` & ``log.html`` after the
test run is complete.
nosetests -v
Adding New Tests
----------------
*See also the Robot* `user guide`_ *for more details on writing test cases.*
#. Add test case to an appropriate test case file: ::
#. Add a test case definition to an appropriate robot test case file: ::
queue/queue_tests.txt
messages/messages_tests.txt
claim/claim_tests.txt).
#. Add test data to the test_data.csv in the same directory as the test case
file you updated above (eg. queue/test_data.csv)
queue/test_queue.py
messages/test_messages.py
claim/test_claims.py
#. Add any validation logic you might need, to the following utility modules:
@ -71,7 +57,3 @@ Adding New Tests
.. _README : https://github.com/stackforge/marconi/blob/master/README.rst
.. _requests : https://pypi.python.org/pypi/requests
.. _robot : https://pypi.python.org/pypi/robotframework
.. _user guide : http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=#.7.7#creating-test-cases

View File

@ -1,66 +0,0 @@
| *Setting* | *Value* |
| Documentation | Marconi - Queue Test Suite |
| Library | ../common/http.py |
| Library | ../common/functionlib.py |
| Library | ../messages/msgfnlib.py |
| Library | Collections |
| Library | claimfnlib.py |
| Variables | getdata.py |
| Force Tags | CLAIM |
| Suite Setup | executetests | ${API_TEST_DATA[6]} | # Test Suite Setup - Creates a Queue
| Suite Teardown | executetests | ${API_TEST_DATA[8]} | # Test Suite Teardown - Deletes the queue created by setup
| *Test Case* | *Action* | *Argument* | *Argument* | *Argument* | # Comment
| 0:SUITE SETUP | [DOCUMENTATION] | | Post 500 messages | | #SUITE SETUP - POST MULTIPLE MESSAGES
| | [Tags] | INSERT_MESSAGE | | | #(Robot allows only one keyword in setup)
| | ${reqparam}= | Create Dictionary | messagecount | ${50} | # Specify count of messages to be posted
| | | ... | ttl | ${300} | # Specify count of messages to be posted
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # Gets the message body to post
| | Set To Dictionary | ${API_TEST_DATA[7]} | body | ${msgbody} | # Set the POST body
| | :FOR | ${index} | IN RANGE | 10 | # Loop to post 50 messages * 10 times
| | | executetests | ${API_TEST_DATA[7]} | | # postresponse = [httpheaders,httpresponsebod]
| 1:CLAIM 2 MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 1 - CLAIM 2 MESSAGES
| | ... | with limit = 2 | |
| | @{postresponse}= | executetests | ${API_TEST_DATA[0]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
| | verifyclaimmsg | ${2} | @{postresponse} |
| 2:CLAIM 5 MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 2 - CLAIM 5 MESSAGES
| | ... | with limit = 5 | |
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
| | verifyclaimmsg | ${5} | @{postresponse} |
| 3:CLAIM MESSAGES | [DOCUMENTATION] | Claim messages | | #TEST CASE 3 - CLAIM DEFAULT # OF MESSAGES
| | ... | with no params | | (currently 10)
| | @{postresponse}= | executetests | ${API_TEST_DATA[2]} | # postresponse = [httpheaders, httpresponsebody]
| | verifyclaimmsg | ${10} | @{postresponse} |
| 4:CLAIM 15 MESSAGE | [DOCUMENTATION] | Claim messages | | #TEST CASE 4 - CLAIM 15 MESSAGES
| | ... | with limit = 15 | |
| | @{postresponse}= | executetests | ${API_TEST_DATA[3]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
| | verifyclaimmsg | ${15} | @{postresponse} |
| 5:CLAIM 55 MESSAGE | [DOCUMENTATION] | Claim messages | | #TEST CASE 5 - CLAIM 55 MESSAGES
| | ... | with limit = 55 | |
| | @{postresponse}= | executetests | ${API_TEST_DATA[4]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
| | verifyclaimmsg | ${50} | @{postresponse} | # MAXIMUM MESSAGES RETURNED IS CURRENTLY 50
| 6: PATCH CLAIM | [DOCUMENTATION] | Patch a claim | | # TEST CASE 6 - UPDATE CLAIM
| | @{postresponse}= | executetests | ${API_TEST_DATA[5]} | # Post a claim; postresponse = [httpheaders, httpresponsebody]
| | patchclaim | @{postresponse} | | # Patch the above claim
| 7: DELETE MESSAGE | [DOCUMENTATION] | Delete message | | # TEST CASE 7 - DELETE A CLAIMED MESSAGE
| | ... | with claim id | |
| | @{postresponse}= | executetests | ${API_TEST_DATA[5]} | # Post a claim
| | deleteclaimedmsgs | @{postresponse} | | # Delete messages returned in the above claim
| 8: PATCH EXPIRED CLAIM | [DOCUMENTATION] | Patch expired claim | | # TEST CASE 8 - UPDATE EXPIRED CLAIM
| | @{postresponse}= | executetests | ${API_TEST_DATA[9]} | # Post a claim with TTL= 1 sec
| | Sleep | 3s | |
| | patchclaim | @{postresponse} | | # Patch the above claim
| 9: DELETE MESSAGE ON EXPIRED CLAIM | [DOCUMENTATION] | Delete message | # TEST CASE 9 - DELETE MESSAGE ON AN EXPIRED CLAIM
| | ... | on expired claim |
| | @{postresponse}= | executetests | ${API_TEST_DATA[10]} | # Post a claim with TTL= 1 sec
| | Sleep | 3s | |
| | deleteclaimedmsgs | @{postresponse} | | # Delete message returned in the above claim
| 10: RELEASE CLAIM | [DOCUMENTATION] | Release claim | | # TEST CASE 10 - RELEASE CLAIM
| | @{postresponse}= | executetests | ${API_TEST_DATA[11]} | # Post a claim with TTL= 1 sec
| | releaseclaim | @{postresponse} | | # Patch the above claim
| 11: GET MESSAGE FROM EXPIRED CLAIM | [DOCUMENTATION] | Get message | # TEST CASE 11 - GET MESSAGE FROM EXPIRED CLAIM
| | ... | from expired claim |
| | @{postresponse}= | executetests | ${API_TEST_DATA[12]} | # Post a claim with TTL= 1 sec
| | Sleep | 3s | |
| | getclaimedmsgs | @{postresponse} | | # Delete message returned in the above claim

View File

@ -28,16 +28,17 @@ def verify_claim_msg(count, *claim_response):
:param count: limit specified in the claim request.
:param claim_response : [header, body] returned for post claim request.
"""
msg_length_flag = False
test_result_flag = False
headers = claim_response[0]
body = claim_response[1]
msg_length_flag = verify_claim_msglength(count, body)
if msg_length_flag:
query_claim(headers, body)
test_result_flag = verify_claim_msglength(count, body)
if test_result_flag:
test_result_flag = query_claim(headers, body)
else:
assert msg_length_flag, 'More msgs returned than specified in limit'
print 'More msgs returned than specified in limit'
return test_result_flag
def verify_claim_msglength(count, *body):
@ -75,9 +76,7 @@ def query_claim(headers, *body):
query_msgs = query_body['messages']
test_result_flag = verify_query_msgs(query_msgs, msg_list)
if test_result_flag:
return test_result_flag
else:
if not test_result_flag:
print 'URL'
print url
print 'HEADER'
@ -88,7 +87,8 @@ def query_claim(headers, *body):
print 'Messages returned by Claim Messages'
print msg_list
print '# of Messages returned by Claim messages', len(msg_list)
assert test_result_flag, 'Query Claim Failed'
print 'Query Claim Failed'
return test_result_flag
def verify_query_msgs(querymsgs, msg_list):
@ -137,10 +137,8 @@ def patch_claim(*claim_response):
print 'Patch HTTP Response code: {}'.format(patch_response.status_code)
print patch_response.headers
print patch_response.text
assert test_result_flag, 'Patch Claim Failed'
if not test_result_flag:
assert test_result_flag, 'Query claim after the patch failed'
return test_result_flag
def verify_patch_claim(url, header, ttl_extended):
@ -198,10 +196,9 @@ def delete_claimed_msgs(*claim_response):
print delete_response.status_code
print delete_response.headers
print delete_response.text
assert test_result_flag, 'Delete Claimed Message Failed'
print 'Delete Claimed Message Failed'
if not test_result_flag:
assert test_result_flag, 'Get message after DELETE did not return 404'
return test_result_flag
def get_claimed_msgs(*claim_response):

View File

@ -1,39 +0,0 @@
# Copyright (c) 2013 Rackspace, Inc.
#
# 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 csv
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
CFG = config.Config()
def get_data():
"""Reads the test data from claim/test_data.csv."""
data = []
with open('marconi/tests/system/claim/test_data.csv', 'rb') as datafile:
testdata = csv.DictReader(datafile, delimiter='|')
for row in testdata:
data.append(row)
for row in data:
row['header'] = functionlib.get_headers(row['header'])
row['url'] = row['url'].replace('<BASE_URL>', CFG.base_url)
return data
API_TEST_DATA = get_data()

View File

@ -0,0 +1,224 @@
# Copyright (c) 2013 Rackspace, Inc.
#
# 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.
from marconi.tests.system.claim import claimfnlib
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
from marconi.tests.system.common import http
from marconi.tests.system.messages import msgfnlib
import testtools
import time
class TestClaims(testtools.TestCase):
"""Tests for Claims."""
def setUp(self):
super(TestClaims, self).setUp()
self.cfg = config.Config()
self.header = functionlib.create_marconi_headers()
def test_000_claim_setup(self):
"""Create Queue, Post Messages for Claim Tests."""
url = self.cfg.base_url + '/queues/claimtestqueue'
doc = '{"queuemetadata": "message test queue"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 201)
#Post Messages
url = self.cfg.base_url + '/queues/claimtestqueue/messages'
doc = msgfnlib.get_message_body(messagecount=50)
for i in range(5):
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 201)
test_000_claim_setup.tags = ['smoke', 'positive']
def test_001_claim_2messages(self):
"""Claim 2 messages."""
message_count = 2
url = self.cfg.base_url + '/queues/claimtestqueue/claims?limit=2'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
test_result_flag = claimfnlib.verify_claim_msg(
message_count, result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_001_claim_2messages.tags = ['smoke', 'positive']
def test_002_claim_default_messages(self):
"""Claim messages with no URL parameters.
By default, Marconi will return 10 messages.
"""
default_message_count = 10
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
test_result_flag = claimfnlib.verify_claim_msg(
default_message_count, result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_002_claim_default_messages.tags = ['smoke', 'positive']
def test_003_claim_15messages(self):
"""Claim 15 messages."""
message_count = 15
url = self.cfg.base_url + '/queues/claimtestqueue/claims?limit=15'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
test_result_flag = claimfnlib.verify_claim_msg(
message_count, result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_003_claim_15messages.tags = ['positive']
def test_004_claim_55messages(self):
"""Claim more than max allowed per request.
Marconi allows a maximum of 50 messages per claim.
"""
message_count = 55
url = self.cfg.base_url + '/queues/claimtestqueue/claims?limit=55'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
test_result_flag = claimfnlib.verify_claim_msg(
message_count, result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_004_claim_55messages.tags = ['positive']
def test_005_claim_patch(self):
"""Update Claim."""
#Test Setup - Post Claim
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
#Update Claim & Verify the patch
test_result_flag = claimfnlib.patch_claim(
result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_005_claim_patch.tags = ['smoke', 'positive']
def test_006_claim_delete_message(self):
"""Delete message belonging to a Claim."""
#Test Setup - Post claim
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 60, "grace": 10}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
#Delete Claimed Message & Verify the delete
test_result_flag = claimfnlib.delete_claimed_msgs(
result.headers, result.text)
self.assertEqual(test_result_flag, True)
test_006_claim_delete_message.tags = ['smoke', 'positive']
def test_007_claim_expired(self):
"""Update, Get and Release Expired Claim."""
#Test Setup - Post Claim.
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 1, "grace": 0}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
time.sleep(2)
#Extract claim location and construct the claim URL.
location = result.headers['Location']
url = self.cfg.base_server + location
#Update Expired Claim.
doc = '{"ttl": 300, "grace": 100}'
result = http.patch(url, self.header, doc)
self.assertEqual(result.status_code, 404)
#Get Expired Claim.
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
#Release Expired Claim.
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 204)
test_007_claim_expired.tags = ['smoke', 'positive']
def test_008_claim_expired_delete_message(self):
"""Get & Delete Message from an Expired Claim."""
#Test Setup - Post Claim.
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 1, "grace": 0}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
time.sleep(2)
#Create url, using message location from claim response.
message_location = result.json()[0]['href']
url = self.cfg.base_server + message_location
#Delete message with expired claim ID
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 403)
test_008_claim_expired_delete_message.tags = ['smoke', 'positive']
def test_009_claim_release(self):
"""Release Claim."""
url = self.cfg.base_url + '/queues/claimtestqueue/claims'
doc = '{"ttl": 300, "grace": 100}'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 200)
#Extract claim location and construct the claim URL.
location = result.headers['Location']
url = self.cfg.base_server + location
#Release Claim.
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 204)
test_009_claim_release.tags = ['smoke', 'positive']
def test_999_claim_teardown(self):
"""Delete Queue after Claim Tests."""
url = self.cfg.base_url + '/queues/claimtestqueue'
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 204)
test_999_claim_teardown.tags = ['smoke', 'positive']

View File

@ -1,15 +0,0 @@
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
1|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 50, "grace": 60}||200|
2|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=5||{"ttl": 50, "grace": 60}||200|
3|POST |<BASE_URL>/queues/claimtestqueue/claims||{"ttl": 50, "grace": 60}||200|
4|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=15||{"ttl": 50, "grace": 60}||200|
5|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=55||{"ttl": 50, "grace": 60}||200|
6|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=4||{"ttl": 50, "grace": 60}||200|
7|PUT |<BASE_URL>/queues/claimtestqueue||{"ttl": 50, "grace": 60}||201|
0|POST |<BASE_URL>/queues/claimtestqueue/messages||||201|
0|DELETE |<BASE_URL>/queues/claimtestqueue||||204|
8|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200|
9|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200|
10|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 50, "grace": 60}||200|
11|POST |<BASE_URL>/queues/claimtestqueue/claims?limit=2||{"ttl": 1, "grace": 1}||200
11|GET |||||200
Can't render this file because it contains an unexpected character in line 2 and column 60.

View File

@ -41,6 +41,10 @@ class Config(object):
def password(self):
return self.parser.get('auth', 'password')
@property
def auth_url(self):
return self.parser.get('auth', 'url')
@property
def base_server(self):
return self.parser.get('marconi_env', 'marconi_url')
@ -49,14 +53,9 @@ class Config(object):
def marconi_version(self):
return self.parser.get('marconi_env', 'marconi_version')
@property
def tenant_id(self):
return self.parser.get('marconi_env', 'tenant_id')
@property
def base_url(self):
return (self.base_server + '/' + self.marconi_version +
'/' + self.tenant_id)
return (self.base_server + '/' + self.marconi_version)
@property
def uuid(self):
@ -69,3 +68,7 @@ class Config(object):
@property
def host(self):
return self.parser.get('header_values', 'host')
@property
def project_id(self):
return self.parser.get('header_values', 'project_id')

View File

@ -16,6 +16,7 @@
import binascii
import json
import os
import string
from marconi.tests.system.common import config
from marconi.tests.system.common import http
@ -49,7 +50,7 @@ def get_keystone_token():
def get_auth_token():
"""Returns a valid auth token if auth is turned on."""
if CFG.auth_enabled == 'true':
if CFG.auth_enabled:
auth_token = get_keystone_token()
else:
auth_token = 'notrealtoken'
@ -61,70 +62,69 @@ def create_marconi_headers():
"""Returns headers to be used for all Marconi requests."""
auth_token = get_auth_token()
headers = '{"Host": "<HOST>","User-Agent": "<USER-AGENT>","Date":"<DATE>",'
headers = '{"Host": "$host","User-Agent": "$user_agent","Date":"DATE",'
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
headers += '"X-Auth-Token": "<auth_token>","Client-ID": "<UUID>"}'
headers = headers.replace('<auth_token>', auth_token)
headers = headers.replace('<HOST>', CFG.host)
headers = headers.replace('<USER-AGENT>', CFG.user_agent)
headers = headers.replace('<UUID>', CFG.uuid)
headers += '"X-Project-ID": "$project_id",'
headers += '"X-Auth-Token": "$token","Client-ID": "$uuid"}'
headers = string.Template(headers)
return headers
return headers.substitute(host=CFG.host, user_agent=CFG.user_agent,
project_id=CFG.project_id,
token=auth_token, uuid=CFG.uuid)
def invalid_auth_token_header():
"""Returns a header with invalid auth token."""
auth_token = get_auth_token()
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
headers = '{"Host":"$host","User-Agent":"$user_agent","Date":"DATE",'
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
headers += 'X-Auth-Token: <auth_token>}'
headers = headers.replace('<auth_token>', auth_token)
headers = headers.replace('<HOST>', CFG.host)
headers = headers.replace('<USER-AGENT>', CFG.user_agent)
headers += '"X-Project-ID": "$project_id",'
headers += '"X-Auth-Token": "InvalidToken"}'
headers = string.Template(headers)
return headers
return headers.substitute(host=CFG.host,
project_id=CFG.project_id,
user_agent=CFG.user_agent)
def missing_header_fields():
"""Returns a header with missing USER_AGENT header."""
"""Returns a header with missing USER_AGENT & X-Project-ID."""
auth_token = get_auth_token()
headers = '{"Host": "<HOST>","Date": "<DATE>",'
headers = '{"Host": "$host","Date": "DATE",'
headers += '"Accept": "application/json","Accept-Encoding": "gzip",'
headers += '"X-Auth-Token": "<auth_token>"}'
headers = headers.replace('<auth_token>', auth_token)
headers = headers.replace('<HOST>', CFG.host)
headers += '"X-Auth-Token": "$token"}'
headers = string.Template(headers)
return headers
return headers.substitute(host=CFG.host, token=auth_token)
def plain_text_in_header():
"""Returns headers to be used for all Marconi requests."""
auth_token = get_auth_token()
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
headers = '{"Host":"$host","User-Agent":"$user_agent","Date":"DATE",'
headers += '"Accept": "text/plain","Accept-Encoding": "gzip",'
headers += '"X-Auth-Token": "<auth_token>"}'
headers = headers.replace('<auth_token>', auth_token)
headers = headers.replace('<HOST>', CFG.host)
headers = headers.replace('<USER-AGENT>', CFG.user_agent)
headers += '"X-Project-ID": "$project_id",'
headers += '"X-Auth-Token": "$token","Client-ID": "$uuid"}'
headers = string.Template(headers)
return headers
return headers.substitute(host=CFG.host, user_agent=CFG.user_agent,
project_id=CFG.project_id,
token=auth_token, uuid=CFG.uuid)
def asterisk_in_header():
"""Returns headers to be used for all Marconi requests."""
auth_token = get_auth_token()
headers = '{"Host":"<HOST>","User-Agent":"<USER-AGENT>","Date":"<DATE>",'
headers = '{"Host":"$host","User-Agent":"$user_agent","Date":"DATE",'
headers += '"Accept": "*/*","Accept-Encoding": "gzip",'
headers += '"X-Auth-Token": "<auth_token>"}'
headers = headers.replace('<auth_token>', auth_token)
headers = headers.replace('<HOST>', CFG.host)
headers = headers.replace('<USER-AGENT>', CFG.user_agent)
headers += '"X-Project-ID": "$project_id",'
headers += '"X-Auth-Token": "$token"}'
headers = string.Template(headers)
return headers
return headers.substitute(host=CFG.host, user_agent=CFG.user_agent,
project_id=CFG.project_id, token=auth_token)
def get_headers(input_header):
@ -146,7 +146,7 @@ def get_headers(input_header):
def get_custom_body(kwargs):
"""Returns a custom request body."""
req_body = {'data': '<DATA>'}
req_body = {'data': '[DATA]'}
if 'metadatasize' in kwargs.keys():
random_data = binascii.b2a_hex(os.urandom(kwargs['metadatasize']))
req_body['data'] = random_data
@ -167,24 +167,6 @@ def get_url_from_location(header):
return url
def verify_metadata(get_data, posted_body):
"""TODO(malini) - Really verify the metadata."""
test_result_flag = False
get_data = str(get_data)
posted_body = str(posted_body)
print(get_data, type(get_data))
print(posted_body, type(posted_body))
if get_data in posted_body:
print('AYYY')
else:
test_result_flag = False
print('NAYYY')
return test_result_flag
def verify_delete(url, header):
"""Verifies the DELETE was successful, with a GET on the deleted item."""
test_result_flag = False
@ -200,6 +182,6 @@ def verify_delete(url, header):
print header
print('Response Body')
print getmsg.text
assert test_result_flag, 'GET Code {}'.format(getmsg.status_code)
print 'GET Code {}'.format(getmsg.status_code)
return test_result_flag

View File

@ -17,12 +17,12 @@ import json
import requests
def get(url, header='', param=''):
def get(url, header=''):
"""Does http GET."""
if header:
header = json.loads(header)
try:
response = requests.get(url, headers=header, params=param)
response = requests.get(url, headers=header)
except requests.ConnectionError as detail:
print('ConnectionError: Exception in http.get {}'.format(detail))
except requests.HTTPError as detail:
@ -34,15 +34,14 @@ def get(url, header='', param=''):
return response
def post(url, header='', body='', param=''):
def post(url, header='', body=''):
"""Does http POST."""
if header:
header = json.loads(header)
body = str(body)
body = body.replace("'", '"')
try:
response = requests.post(url, headers=header, data=body,
params=param)
response = requests.post(url, headers=header, data=body)
except requests.ConnectionError as detail:
print('ConnectionError: Exception in http.post {}'.format(detail))
except requests.HTTPError as detail:
@ -54,15 +53,14 @@ def post(url, header='', body='', param=''):
return response
def put(url, header='', body='', param=''):
def put(url, header='', body=''):
"""Does http PUT."""
response = None
if header:
header = json.loads(header)
try:
response = requests.put(url, headers=header, data=body,
params=param)
response = requests.put(url, headers=header, data=body)
except requests.ConnectionError as detail:
print('ConnectionError: Exception in http.put {}'.format(detail))
except requests.HTTPError as detail:
@ -74,14 +72,14 @@ def put(url, header='', body='', param=''):
return response
def delete(url, header='', param=''):
def delete(url, header=''):
"""Does http DELETE."""
response = None
if header:
header = json.loads(header)
try:
response = requests.delete(url, headers=header, params=param)
response = requests.delete(url, headers=header)
except requests.ConnectionError as detail:
print('ConnectionError: Exception in http.delete {}'.format(detail))
except requests.HTTPError as detail:
@ -93,15 +91,14 @@ def delete(url, header='', param=''):
return response
def patch(url, header='', body='', param=''):
def patch(url, header='', body=''):
"""Does http PATCH."""
response = None
if header:
header = json.loads(header)
try:
response = requests.patch(url, headers=header, data=body,
params=param)
response = requests.patch(url, headers=header, data=body)
except requests.ConnectionError as detail:
print('ConnectionError: Exception in http.patch {}'.format(detail))
except requests.HTTPError as detail:
@ -111,68 +108,3 @@ def patch(url, header='', body='', param=''):
except requests.TooManyRedirects as detail:
print('TooManyRedirects: Exception in http.patch {}'.format(detail))
return response
def executetests(row):
"""Entry Point for all tests.
Executes the tests defined in the *_tests.txt,
using the test data from *_data.csv.
"""
http_verb = row['httpverb'].strip()
url = row['url']
header = row['header']
params = row['params']
body = row['body']
expected_RC = row['expectedRC']
expected_RC = int(expected_RC)
expected_response_body = row['expectedResponseBody']
response = None
if http_verb == 'GET':
response = get(url, header, params)
elif http_verb == 'POST':
response = post(url, header, body, params)
elif http_verb == 'PUT':
response = put(url, header, body, params)
elif http_verb == 'DELETE':
response = delete(url, header, params)
elif http_verb == 'PATCH':
response = patch(url, header, body, params)
if response is not None:
test_result_flag = verify_response(response, expected_RC)
else:
test_result_flag = False
if test_result_flag:
return response.headers, response.text
else:
print http_verb
print url
print header
print body
print 'Actual Response: {}'.format(response.status_code)
print 'Actual Response Headers'
print response.headers
print'Actual Response Body'
print response.text
print'ExpectedRC: {}'.format(expected_RC)
print'expectedresponsebody: {}'.format(expected_response_body)
assert test_result_flag, 'Actual Response does not match the Expected'
def verify_response(response, expected_RC):
"""Compares the http Response code with the expected Response code."""
test_result_flag = True
actual_RC = response.status_code
actual_response_body = response.text
if actual_RC != expected_RC:
test_result_flag = False
print('Unexpected http Response code {}'.format(actual_RC))
print 'Response Body returned'
print actual_response_body
return test_result_flag

View File

@ -6,10 +6,10 @@ username = user
password = secret
[marconi_env]
marconi_url = http://166.78.143.130:80
marconi_url = http://0.0.0.0:8888
marconi_version = v1
tenant_id = 1
[header_values]
host = marconi.test.com
useragent = systemtests
useragent = systemtests
project_id = 123456

View File

@ -1,40 +0,0 @@
# Copyright (c) 2013 Rackspace, Inc.
#
# 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 csv
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
CFG = config.Config()
def get_data():
"""Gets Test data from a csv file."""
data = []
with open('marconi/tests/system/messages/test_data.csv', 'rb') as datafile:
test_data = csv.DictReader(datafile, delimiter='|')
for row in test_data:
data.append(row)
for row in data:
row['header'] = functionlib.get_headers(row['header'])
row['url'] = row['url'].replace('<BASE_URL>', CFG.base_url)
return data
API_TEST_DATA = get_data()

View File

@ -1,53 +0,0 @@
| *Setting* | *Value* |
| Documentation | Marconi - Message Test Suite |
| Library | ../common/http.py |
| Library | ../common/functionlib.py |
| Library | msgfnlib.py |
| Library | Collections |
| Variables | getdata.py |
| Force Tags | MESSAGES |
| Suite Setup | executetests | ${API_TEST_DATA[0]} | # Test Suite Setup - Creates a Queue
| Suite Teardown | executetests | ${API_TEST_DATA[7]} | # Test Suite Teardown - Deletes the queue created by setup
| *Test Case* | *Action* | *Argument* | *Argument* | *Argument* | # Comment
| 1:POST SINGLE MESSAGE | [DOCUMENTATION] | | Post single message | | #TEST CASE 1 - POST SINGLE MESSAGE
| | [Tags] | INSERT_MESSAGE | | |
| | ${reqparam}= | Create Dictionary | messagecount | ${1} | # test Setup- Specify count of messages to be posted
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
| | Set To Dictionary | ${API_TEST_DATA[1]} | body | ${msgbody} | # test Setup -Set the POST body
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | | # postresponse = [httpheaders, httpresponsebody] |
| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[1]["body"]} | | # GET the posted message & verify metadata
| |
| 2:POST MULTIPLE MESSAGES | [DOCUMENTATION] | | Post 50 messages | | #TEST CASE 2 - POST MULTIPLE MESSAGES
| | [Tags] | INSERT_MESSAGE | | |
| | ${reqparam}= | Create Dictionary | messagecount | ${50} | # Specify count of messages to be posted
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # Gets the message body to post
| | Set To Dictionary | ${API_TEST_DATA[2]} | body | ${msgbody} | # Set the POST body
| | @{postresponse}= | executetests | ${API_TEST_DATA[2]} | | # postresponse = [httpheaders, httpresponsebody]
#| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[2]["body"]} | | # GET the posted messages & verify metadata
| |
| 3:GET MESSAGES-no params | [DOCUMENTATION] | Get message with no params | | # TEST CASE 3 - GET MESSAGE WITH NO PARAMS
| | @{getresponse}= | executetests | ${API_TEST_DATA[3]} |
| | verifygetmsgs | ${10} | @{getresponse} | # Verifies that number of messages returned is <= 10
| |
| 4:GET MESSAGES-limit=5 | [DOCUMENTATION] | Get message with limit = 5 | | # TEST CASE 4 - GET MESSAGE WITH limit = 5
| | @{getresponse}= | executetests | ${API_TEST_DATA[4]} |
| | verifygetmsgs | ${5} | @{getresponse} | # Verifies that number of messages returned is <= 5
| 5:GET MESSAGES-echo=False | [DOCUMENTATION] | Get message with echo=False | | # TEST CASE 5 - GET MESSAGE WITH echo = False
| | @{getresponse}= | executetests | ${API_TEST_DATA[5]} |
| | verifygetmsgs | ${10} | @{getresponse} | # Verifies that number of messages returned is <= 10
| 6:DELETE MESSAGE | [DOCUMENTATION] | | Delete message | | #TEST CASE 6 - DELETE MESSAGE
| | [Tags] | INSERT_MESSAGE | | |
| | ${reqparam}= | Create Dictionary | messagecount | ${1} | # test Setup- Specify count of messages to be posted
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
| | Set To Dictionary | ${API_TEST_DATA[1]} | body | ${msgbody} | # test Setup -Set the POST body
| | @{postresponse}= | executetests | ${API_TEST_DATA[1]} | | # postresponse = [httpheaders, httpresponsebody] |
| | deletemsg | ${postresponse[0]} | | | # GET the posted message & verify metadata
| 7:POST 60 MESSAGES | [DOCUMENTATION] | POST > MAX NUMBER OF MESSAGES | | | #TEST CASE 7 - POST > 50 MESSAGES
| | ... | ALLOWED PER POST (currently 50) | | |
| | [Tags] | INSERT_MESSAGE | | |
| | ${reqparam}= | Create Dictionary | messagecount | ${60} | # test Setup- Specify count of messages to be posted
| | ${msgbody}= | dummygetmessagebody | ${reqparam} | | # test Setup- Get the message body to post
| | Set To Dictionary | ${API_TEST_DATA[6]} | body | ${msgbody} | # test Setup -Set the POST body
| | @{postresponse}= | executetests | ${API_TEST_DATA[6]} | | # postresponse = [httpheaders, httpresponsebody] |
| | verifypostmsg | ${postresponse[0]} | ${API_TEST_DATA[6]["body"]} | | # GET the posted message & verify metadata

View File

@ -22,9 +22,6 @@ from marconi.tests.system.common import functionlib
from marconi.tests.system.common import http
CFG = config.Config()
def generate_dict(dict_length):
"""Returns dictionary of specified length. Key:Value is random data.
@ -72,21 +69,16 @@ def get_message_body(**kwargs):
"""
message_count = kwargs['messagecount']
multiple_message_body = []
for i in range[message_count]:
for i in range(message_count):
message_body = single_message_body(**kwargs)
multiple_message_body.append(message_body)
return multiple_message_body
def dummyget_message_body(dict):
"""Dummy function since Robot framework does not support **kwargs."""
dict = get_message_body(**dict)
return dict
def create_url(base_url=CFG.base_url, *msg_id_list):
def create_url(*msg_id_list):
"""Creates url list for retrieving messages with message id."""
url = [(base_url + msg_id) for msg_id in msg_id_list]
cfg = config.Config()
url = [(cfg.base_url + msg_id) for msg_id in msg_id_list]
return url
@ -133,8 +125,7 @@ def verify_post_msg(msg_headers, posted_body):
getmsg = http.get(url, header)
if getmsg.status_code == 200:
test_result_flag = functionlib.verify_metadata(getmsg.text,
posted_body)
test_result_flag = True
else:
print('Failed to GET {}'.format(url))
print('Request Header')
@ -143,7 +134,7 @@ def verify_post_msg(msg_headers, posted_body):
print getmsg.headers
print('Response Body')
print getmsg.text
assert test_result_flag, 'HTTP code {}'.format(getmsg.status_code)
return test_result_flag
def get_next_msgset(responsetext):
@ -184,8 +175,7 @@ def verify_get_msgs(count, *getresponse):
print('Messages returned exceed requested number of messages')
test_result_flag = False
if not test_result_flag:
assert test_result_flag, 'Recursive Get Messages Failed'
return test_result_flag
def delete_msg(*postresponse):
@ -211,4 +201,6 @@ def delete_msg(*postresponse):
print header
print('Response Body')
print deletemsg.text
assert test_result_flag, 'DELETE Code {}'.format(deletemsg.status_code)
print 'DELETE Code {}'.format(deletemsg.status_code)
return test_result_flag

View File

@ -1,9 +0,0 @@
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
0|PUT |<BASE_URL>/queues/msgtestqueue||{"messages":{"ttl": 86400}}||201|
1|POST |<BASE_URL>/queues/msgtestqueue/messages||||201|
2|POST |<BASE_URL>/queues/msgtestqueue/messages||||201|
3|GET |<BASE_URL>/queues/msgtestqueue/messages?echo=true||||200|
4|GET |<BASE_URL>/queues/msgtestqueue/messages?limit=5&echo=true||||200|
5|GET |<BASE_URL>/queues/msgtestqueue/messages?limit=5&echo=true||||200|
6|POST |<BASE_URL>/queues/msgtestqueue/messages||{"messages":{"ttl": 86400}}||201|
0|DELETE |<BASE_URL>/queues/msgtestqueue||||204|
Can't render this file because it contains an unexpected character in line 2 and column 44.

View File

@ -0,0 +1,158 @@
# Copyright (c) 2013 Rackspace, Inc.
#
# 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.
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
from marconi.tests.system.common import http
from marconi.tests.system.messages import msgfnlib
import testtools
class TestMessages(testtools.TestCase):
"""Tests for Messages."""
def setUp(self):
super(TestMessages, self).setUp()
self.cfg = config.Config()
self.header = functionlib.create_marconi_headers()
def test_000_message_setup(self):
"""Create Queue for Message Tests."""
url = self.cfg.base_url + '/queues/messagetestqueue'
doc = '{"queuemetadata": "message test queue"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 201)
test_000_message_setup.tags = ['smoke', 'positive']
def test_001_message_single_insert(self):
"""Insert Single Message into the Queue."""
doc = msgfnlib.get_message_body(messagecount=1)
url = self.cfg.base_url + '/queues/messagetestqueue/messages'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 201)
#GET on posted message
location = result.headers['location']
url = self.cfg.base_server + location
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
#Compare message metadata
result_body = result.json()['body']
posted_metadata = doc[0]['body']
self.assertEqual(result_body, posted_metadata)
test_001_message_single_insert.tags = ['smoke', 'positive']
def test_002_message_bulk_insert(self):
"""Bulk Insert Messages into the Queue."""
doc = msgfnlib.get_message_body(messagecount=30)
url = self.cfg.base_url + '/queues/messagetestqueue/messages'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 201)
#GET on posted messages
location = result.headers['location']
url = self.cfg.base_server + location
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
#Compare message metadata
result_body = result.json()['body']
posted_metadata = doc[0]['body']
self.assertEqual(result_body, posted_metadata)
test_002_message_bulk_insert.tags = ['smoke', 'positive']
def test_003_message_get_no_params(self):
"""Get Messages with no params."""
default_msg_count = 10
url = self.cfg.base_url + '/queues/messagetestqueue/messages'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
test_result_flag = msgfnlib.verify_get_msgs(default_msg_count,
result.headers,
result.text)
self.assertEqual(test_result_flag, True)
test_003_message_get_no_params.tags = ['smoke', 'positive']
def test_004_message_get_limit_5(self):
"""Get Messages with no params."""
msg_count = 5
url = self.cfg.base_url + '/queues/messagetestqueue/messages?limit=5'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
test_result_flag = msgfnlib.verify_get_msgs(msg_count,
result.headers,
result.text)
self.assertEqual(test_result_flag, True)
test_004_message_get_limit_5.tags = ['smoke', 'positive']
def test_005_message_get_echo_false(self):
"""Get Messages with echo=false."""
url = self.cfg.base_url + \
'/queues/messagetestqueue/messages?echo=false'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 204)
test_005_message_get_echo_false.tags = ['smoke', 'positive']
def test_006_message_delete(self):
"""Delete Message."""
doc = msgfnlib.get_message_body(messagecount=1)
url = self.cfg.base_url + '/queues/messagetestqueue/messages'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 201)
#Delete posted message
location = result.headers['location']
url = self.cfg.base_server + location
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 204)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_006_message_delete.tags = ['smoke', 'positive']
def test_007_message_bulk_insert_60(self):
"""Insert more than max allowed messages.
Marconi allows a maximum of 50 message per POST.
"""
doc = msgfnlib.get_message_body(messagecount=60)
url = self.cfg.base_url + '/queues/messagetestqueue/messages'
result = http.post(url, self.header, doc)
self.assertEqual(result.status_code, 400)
test_007_message_bulk_insert_60.tags = ['negative']
def test_999_message_teardown(self):
url = self.cfg.base_url + '/queues/messagetestqueue'
http.delete(url, self.header)
test_999_message_teardown.tags = ['smoke', 'positive']

View File

@ -1,39 +0,0 @@
# Copyright (c) 2013 Rackspace, Inc.
#
# 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 csv
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
CFG = config.Config()
def get_data():
"""Gets Test data from a csv file."""
data = []
with open('marconi/tests/system/queue/test_data.csv', 'rb') as datafile:
test_data = csv.DictReader(datafile, delimiter='|')
for row in test_data:
data.append(row)
for row in data:
row['header'] = functionlib.get_headers(row['header'])
row['url'] = row['url'].replace('<BASE_URL>', CFG.base_url)
return data
API_TEST_DATA = get_data()

View File

@ -1,106 +0,0 @@
| *Setting* | *Value* |
| Documentation | Marconi - Queue Test Suite |
| Library | ../common/http.py |
| Library | queuefnlib.py |
| Library | ../common/functionlib.py |
| Library | Collections |
| Variables | getdata.py |
| Force Tags | QUEUE |
| *Test Case* | *Action* | *Argument* | *Argument* |
| 1: PUT QUEUE | [DOCUMENTATION] | Creates, gets & verifies | |
| | ... | Queue | |
| | @{putresponse}= | executetests | ${API_TEST_DATA[0]} |
| | ${url}= | geturlfromlocation | ${putresponse[0]} |
| | ${getresponse}= | executetests | ${API_TEST_DATA[1]} |
| | verifymetadata | ${API_TEST_DATA[0]["body"]} | ${getresponse} |
| 2: PUT QUEUE | [DOCUMENTATION] | Verifies that queue name | |
| | ... | are NOT case sensitive | |
| | ${putresponse}= | executetests | ${API_TEST_DATA[2]} |
| | ${getresponse}= | executetests | ${API_TEST_DATA[3]} |
| | verifymetadata | ${API_TEST_DATA[2]["body"]} | ${getresponse} |
| 3: UPDATE QUEUE | [DOCUMENTATION] | Updates an existing queue | |
| | ${putresponse}= | executetests | ${API_TEST_DATA[4]} |
| | ${getresponse}= | executetests | ${API_TEST_DATA[5]} |
| | verifymetadata | ${API_TEST_DATA[4]["body"]} | ${getresponse} |
| 4: PUT QUEUE | [DOCUMENTATION] | Create Queue with no request | |
| | ... | body | |
| | executetests | ${API_TEST_DATA[6]} | |
| 5: PUT QUEUE | [DOCUMENTATION] | Create Queue with invalid | |
| | ... | Authtoken | |
| | ${header}= | invalidauthtokenheader | |
| | Set To Dictionary | ${API_TEST_DATA[7]} | header | ${header} | # test Setup -Set the POST header
| | executetests | ${API_TEST_DATA[7]} | |
| 6: PUT QUEUE | [DOCUMENTATION] | Create Queue with missing | |
| | ... | header field USERAGENT | |
| | ${header}= | missingheaderfields | |
| | Set To Dictionary | ${API_TEST_DATA[8]} | header | ${header} | # test Setup -Set the POST header
| | executetests | ${API_TEST_DATA[8]} | |
| 7: PUT QUEUE | [DOCUMENTATION] | Verifies metadata toplevel | |
| | ... | field do not start with _ | |
| | executetests | ${API_TEST_DATA[9]} | |
| 8: PUT QUEUE | [DOCUMENTATION] | Header has Accept value that | |
| | ... | is not "application/json" | |
| | ${header}= | plaintextinheader | |
| | Set To Dictionary | ${API_TEST_DATA[10]} | header | ${header} | # test Setup -Set the POST header
| | executetests | ${API_TEST_DATA[10]} | |
| 9: PUT QUEUE | [DOCUMENTATION] | Header has Accept value that | |
| | ... | is "\*/\*" | |
| | ${header}= | asteriskinheader | |
| | Set To Dictionary | ${API_TEST_DATA[11]} | header | ${header} | # test Setup -Set the POST header
| | executetests | ${API_TEST_DATA[11]} | |
| 10: PUT QUEUE | [DOCUMENTATION] | Create queue with Non ASCII | |
| | ... | characters in name | |
| | executetests | ${API_TEST_DATA[12]} | |
| 11: PUT QUEUE | [DOCUMENTATION] | Create queue with Non ASCII | |
| | ... | characters in body | |
| | executetests | ${API_TEST_DATA[13]} | |
| 12: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
| | ... | size = 4KB | |
| | ${reqdata}= | Create Dictionary | metadatasize | ${4096} |
| | ${body}= | getcustombody | ${reqdata} |
| | Set To Dictionary | ${API_TEST_DATA[14]} | body | ${body} | # test Setup -Set the POST body
| | executetests | ${API_TEST_DATA[14]} | |
| 13: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
| | ... | size = 4KB + 1 | |
| | ${reqdata}= | Create Dictionary | metadatasize | ${4097} |
| | ${body}= | getcustombody | ${reqdata} |
| | Set To Dictionary | ${API_TEST_DATA[15]} | body | ${body} | # test Setup -Set the POST body
| | executetests | ${API_TEST_DATA[15]} | |
| 14: PUT QUEUE | [DOCUMENTATION] | Create queue with metadata | |
| | ... | size = 4KB - 1 | |
| | ${reqdata}= | Create Dictionary | metadatasize | ${4095} |
| | ${body}= | getcustombody | ${reqdata} |
| | Set To Dictionary | ${API_TEST_DATA[16]} | body | ${body} | # test Setup -Set the POST body
| | executetests | ${API_TEST_DATA[16]} | |
| 15: PUT QUEUE | [DOCUMENTATION] | Create queue with name | |
| | ... | longer than 64 char | |
| | ${url}= | getqueuename | |
| | Set To Dictionary | ${API_TEST_DATA[17]} | url | ${url} | # test Setup -Set the PUT url
| | executetests | ${API_TEST_DATA[17]} | |
| 16: GET QUEUE STATS | [DOCUMENTATION] | Get Queue Stats | |
| | @{getresponse}= | executetests | ${API_TEST_DATA[18]} |
| | verifyqueuestats | @{getresponse} | |
| 17: LIST QUEUES | [DOCUMENTATION] | List queues with no params | |
| | @{listqueues}= | executetests | ${API_TEST_DATA[19]} |
| | verifylistqueues | @{listqueues} | |
| 18: LIST QUEUES DETAILED | [DOCUMENTATION] | List queues ?detailed=true | |
| | @{listqueues}= | executetests | ${API_TEST_DATA[20]} |
| | verifylistqueues | @{listqueues} | |
| 19: DELETE QUEUE | [DOCUMENTATION] | Delete a queue | |
| | executetests | ${API_TEST_DATA[21]} | |
| 20: PUT QUEUE | [DOCUMENTATION] | Creates a queue with same | |
| | ... | name as deleted | |
| | @{putresponse}= | executetests | ${API_TEST_DATA[22]} |
| | ${url}= | geturlfromlocation | ${putresponse[0]} |
| | ${getresponse}= | executetests | ${API_TEST_DATA[23]} |
| | verifymetadata | ${API_TEST_DATA[22]["body"]} | ${getresponse} |
| 21: PUT QUEUE | [DOCUMENTATION] | Create Queue with invalid | |
| | ... | char in metadata | |
| | executetests | ${API_TEST_DATA[24]} | |
| 22: DELETE QUEUE | [DOCUMENTATION] | Delete a queue | |
| | executetests | ${API_TEST_DATA[25]} | |
| 23: GET QUEUE - 404 | [DOCUMENTATION] | Get non existing queue | |
| | executetests | ${API_TEST_DATA[26]} | |

View File

@ -69,8 +69,7 @@ def get_queue_name(namelength=65):
"""
appender = '/queues/' + binascii.b2a_hex(os.urandom(namelength))
url = functionlib.create_url_from_appender(appender)
return url
return appender
def verify_list_queues(*list_queue_response):
@ -78,6 +77,7 @@ def verify_list_queues(*list_queue_response):
:param *list_queue_response: [header, body] returned for list queue.
"""
test_result_flag = True
response_body = json.loads(list_queue_response[1])
links = response_body['links']
href = links[0]['href']
@ -90,10 +90,12 @@ def verify_list_queues(*list_queue_response):
if False in test_result_flags:
test_result_flag = False
print 'List Queue API response: {}'.format(response_body)
assert test_result_flag, 'List Queue failed'
return test_result_flag
if links[0]['rel'] == 'next':
list_queues(href)
test_result_flag = list_queues(href)
return test_result_flag
def verify_listed(queue, detail_enabled):
@ -136,8 +138,7 @@ def list_queues(href):
if list_queue_response.status_code == 200:
headers = list_queue_response.headers
text = list_queue_response.text
verify_list_queues(headers, text)
test_result_flag = verify_list_queues(headers, text)
elif list_queue_response.status_code == 204:
test_result_flag = True
else:
assert test_result_flag, 'List Queue failed'
return test_result_flag

View File

@ -1,28 +0,0 @@
TestID|httpverb|url|header|body|params|expectedRC|expectedResponseBody
1|PUT |<BASE_URL>/queues/qtestqueue||{"messages":{"ttl": 86400}}||201|
1|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
2|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||204|
2|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
3|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||204|
3|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
4|PUT |<BASE_URL>/queues/qtestqueue||||400|{"title": "Bad request","description": "Missing queue metadata."}
5|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||401|
6|PUT |<BASE_URL>/queues/qtestqueue||{"messages": {"ttl": 86400}}||400|
7|PUT |<BASE_URL>/queues/qtestqueue||{"_TOPLEVEL": {"ttl": 86400}}||400|
8|PUT |<BASE_URL>/queues/qtestqueue||{"TOPLEVEL": {"ttl": 86400}}||406|
9|PUT |<BASE_URL>/queues/qtestqueue||{"TOPLEVEL": {"ttl": 86400}}||200|
10|PUT |<BASE_URL>/queues/汉字/漢字||{"messages": {"ttl": 86400}}||201|
11|PUT |<BASE_URL>/queues/qtestqueue||{"汉字": {"ttl": 86400}}||201|
12|PUT |<BASE_URL>/queues/qtestqueue||||201|
13|PUT |<BASE_URL>/queues/qtestqueue||||400|
14|PUT |<BASE_URL>/queues/qtestqueue||||204|
15|PUT |||{"messages":{"ttl": 86400}}||400|
16|GET |<BASE_URL>/queues/qtestqueue/stats||||200|
17|GET |<BASE_URL>/queues?limit=1||||200|
18|GET |<BASE_URL>/queues?detailed=true||||200|
19|DELETE |<BASE_URL>/queues/qtestqueue||||204|
20|PUT |<BASE_URL>/queues/qtestqueue||{"messages":{"ttl": 86400}}||201|
20|GET |<BASE_URL>/queues/qtestqueue||||200|{"ttl": 86400}
21|PUT |<BASE_URL>/queues/qtestqueue||{"mess~&%^":{"ttl": 86400}}||400|
22|DELETE |<BASE_URL>/queues/qtestqueue||||204|
23|GET |<BASE_URL>/queues/nonexistingqueue||||404|
Can't render this file because it contains an unexpected character in line 2 and column 43.

View File

@ -0,0 +1,331 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2013 Rackspace, Inc.
#
# 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 testtools
from marconi.tests.system.common import config
from marconi.tests.system.common import functionlib
from marconi.tests.system.common import http
from marconi.tests.system.queue import queuefnlib
import json
class TestQueue(testtools.TestCase):
"""Tests for queue."""
def setUp(self):
super(TestQueue, self).setUp()
self.cfg = config.Config()
self.header = functionlib.create_marconi_headers()
def test_001_queue_insert(self):
"""Insert Queue.
Creates Queue, does a get & verifies data.
"""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = '{"queue": "Apple"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 201)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc))
test_001_queue_insert.tags = ['smoke', 'positive', 'create_queue']
def test_002_queue_insert_case_insensitive(self):
"""Insert Queue with same name, different case."""
url = self.cfg.base_url + '/queues/QteStquEue'
doc = '{"queue": "Orange"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 201)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc))
http.delete(url, self.header)
test_002_queue_insert_case_insensitive.tags = ['positive']
def test_003_queue_update_empty_metadata(self):
"""Update Queue with empty metadata."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc_original = '{"queue": "Apple"}'
doc = ''
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc_original))
test_003_queue_update_empty_metadata.tags = ['negative']
def test_004_queue_update_empty_json(self):
"""Update Queue with empty json."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = '{}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 204)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc))
test_004_queue_update_empty_json.tags = ['smoke', 'positive']
def test_005_queue_insert_invalid_authtoken(self):
"""Insert Queue with invalid authtoken."""
url = self.cfg.base_url + '/queues/invalidauthtoken'
header = functionlib.invalid_auth_token_header()
doc = '{"queue": "invalid auth token"}'
result = http.put(url, header, doc)
self.assertEqual(result.status_code, 401)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_005_queue_insert_invalid_authtoken.tags = ['negative']
def test_006_queue_update_invalid_authtoken(self):
"""Update Queue with invalid authtoken."""
url = self.cfg.base_url + '/queues/qtestqueue'
header = functionlib.invalid_auth_token_header()
doc = '{"queue": "invalid auth token"}'
doc_original = '{}'
result = http.put(url, header, doc)
self.assertEqual(result.status_code, 401)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc_original))
test_006_queue_update_invalid_authtoken.tags = ['negative']
def test_007_queue_insert_missing_header(self):
"""Insert Queue with missing header field.
Request has no USER_AGENT & X-Project-Id headers.
"""
url = self.cfg.base_url + '/queues/missingheader'
header = functionlib.missing_header_fields()
doc = '{"queue": "USER_AGENT header is missing"}'
result = http.put(url, header, doc)
self.assertEqual(result.status_code, 400)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_007_queue_insert_missing_header.tags = ['negative']
def test_008_queue_insert_toplevel_underscore(self):
"""Insert Queue with underscore in toplevel field."""
url = self.cfg.base_url + '/queues/toplevel'
doc = '{"_queue": "Top Level field with _"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_008_queue_insert_toplevel_underscore.tags = ['negative']
def test_009_queue_insert_header_plaintext(self):
"""Insert Queue with 'Accept': 'plain/text'."""
url = self.cfg.base_url + '/queues/plaintextheader'
header = functionlib.plain_text_in_header()
doc = '{"queue": "text/plain in header"}'
result = http.put(url, header, doc)
self.assertEqual(result.status_code, 406)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_009_queue_insert_header_plaintext.tags = ['negative']
def test_010_queue_insert_header_asterisk(self):
"""Insert Queue with 'Accept': '*/*'."""
url = self.cfg.base_url + '/queues/asteriskinheader'
header = functionlib.asterisk_in_header()
doc = '{"queue": "*/* in header"}'
result = http.put(url, header, doc)
self.assertEqual(result.status_code, 201)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
http.delete(url, self.header)
test_010_queue_insert_header_asterisk.tags = ['positive']
def test_011_queue_insert_nonASCII_name(self):
"""Insert Queue with non ASCII name."""
url = self.cfg.base_url + '/queues/汉字/漢字'
doc = '{"queue": "non ASCII name"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_011_queue_insert_nonASCII_name.tags = ['negative']
def test_012_queue_insert_nonASCII_metadata(self):
"""Insert Queue with non ASCII name."""
url = self.cfg.base_url + '/queues/nonASCIImetadata'
doc = '{"汉字": "non ASCII metadata"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_012_queue_insert_nonASCII_metadata.tags = ['negative']
def test_013_queue_update_metadata_size4095(self):
"""Updates Queue with metadata_size = 4095."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = functionlib.get_custom_body({"metadatasize": 4095})
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 204)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc))
test_013_queue_update_metadata_size4095.tags = ['positive']
def test_014_queue_update_metadata_size4096(self):
"""Updates Queue with metadata_size = 4096."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = functionlib.get_custom_body({"metadatasize": 4096})
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 204)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
self.assertEqual(result.json(), json.loads(doc))
test_014_queue_update_metadata_size4096.tags = ['positive']
def test_015_queue_update_metadata_size4097(self):
"""Updates Queue with metadata_size = 4097."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = functionlib.get_custom_body({"metadatasize": 4097})
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
test_015_queue_update_metadata_size4097.tags = ['negative']
def test_016_queue_insert_long_queuename(self):
"""Insert queue with name > 64 bytes."""
url = self.cfg.base_url + queuefnlib.get_queue_name()
doc = '{"queue": "Longer than allowed queue name"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
test_016_queue_insert_long_queuename.tags = ['negative']
def test_017_queue_stats(self):
"""Insert queue with name > 64 bytes."""
url = self.cfg.base_url + '/queues/qtestqueue/stats'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
test_result_flag = queuefnlib.verify_queue_stats(result.headers,
result.text)
self.assertEqual(test_result_flag, True)
test_017_queue_stats.tags = ['smoke', 'positive']
def test_018_queue_list(self):
"""List Queues."""
url = self.cfg.base_url + '/queues'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
test_result_flag = queuefnlib.verify_list_queues(result.headers,
result.text)
self.assertEqual(test_result_flag, True)
test_018_queue_list.tags = ['smoke', 'positive']
def test_019_queue_list_detailed(self):
"""List Queues with detailed = True."""
url = self.cfg.base_url + '/queues?detailed=True'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 200)
test_result_flag = queuefnlib.verify_list_queues(result.headers,
result.text)
self.assertEqual(test_result_flag, True)
test_019_queue_list_detailed.tags = ['smoke', 'positive']
def test_020_queue_insert_metadata_invalidchar(self):
"""Update Queues with invalid char in metadata."""
url = self.cfg.base_url + '/queues/qtestqueue'
doc = '{"queue": "#$%^&Apple"}'
result = http.put(url, self.header, doc)
self.assertEqual(result.status_code, 400)
test_020_queue_insert_metadata_invalidchar.tags = ['negative']
def test_021_queue_get_nonexisting(self):
"""Update Queues with invalid char in metadata."""
url = self.cfg.base_url + '/queues/nonexistingqueue'
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_021_queue_get_nonexisting.tags = ['negative']
def test_999_delete_queue(self):
"""Delete Queue.
Deletes Queue & performs GET to confirm 404.
"""
url = self.cfg.base_url + '/queues/qtestqueue'
result = http.delete(url, self.header)
self.assertEqual(result.status_code, 204)
result = http.get(url, self.header)
self.assertEqual(result.status_code, 404)
test_999_delete_queue.tags = ['smoke']

View File

@ -1,2 +1 @@
robotframework
requests