Skip to content

Commit

Permalink
Feature: support query string as an argument in lobster codebeamer
Browse files Browse the repository at this point in the history
Query string (CBQL query) can be now passed as a command line argument to the lobster codebeamer tool
  • Loading branch information
mugdhadhole1 committed Dec 13, 2024
1 parent 3bf1317 commit 7772b7c
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 21 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

### 0.9.21-dev

* `lobster-codebeamer` now supports query string, query string (CBQL) can be passed
as a command line argument to the tool `lobster-codebeamer`.

* `lobster-html-report` has the following updates.
* Filter items by status (Ok, Missing, Partial, Warning, Justified)
* Hide/Unhide Issues.
Expand Down
60 changes: 42 additions & 18 deletions lobster/tools/codebeamer/codebeamer.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,30 @@ def get_many_items(cb_config, item_ids):
return rv


def get_query(mh, cb_config, query_id):
def get_query(mh, cb_config, query):
assert isinstance(mh, Message_Handler)
assert isinstance(cb_config, dict)
assert isinstance(query_id, int)
assert isinstance(query, (int, str))
rv = []
url = ""
page_id = 1
total_items = None

while total_items is None or len(rv) < total_items:
print("Fetching page %u of query..." % page_id)
url = "%s/reports/%u/items?page=%u&pageSize=%u" % \
(cb_config["base"],
query_id,
page_id,
cb_config["page_size"])
data = query_cb_single(cb_config, url)
assert len(data) == 4
if query is not None:
if isinstance(query, int):
url = ("%s/reports/%u/items?page=%u&pageSize=%u" %
(cb_config["base"],
query,
page_id,
cb_config["page_size"]))
elif isinstance(query, str):
url = ("%s/items/query?queryString=%s" %
(cb_config["base"],
query))
data = query_cb_single(cb_config, url)
assert len(data) == 4

if page_id == 1 and len(data["items"]) == 0:
print("This query doesn't generate items. Please check:")
Expand All @@ -183,8 +190,12 @@ def get_query(mh, cb_config, query_id):
else:
assert total_items == data["total"]

rv += [to_lobster(cb_config, cb_item["item"])
for cb_item in data["items"]]
if query is not None and isinstance(query, int):
rv += [to_lobster(cb_config, cb_item["item"])
for cb_item in data["items"]]
elif query is not None and isinstance(query, str):
rv += [to_lobster(cb_config, cb_item)
for cb_item in data["items"]]

page_id += 1

Expand Down Expand Up @@ -416,7 +427,7 @@ def main():
default=None)

modes.add_argument("--import-query",
metavar="CB_QUERY_ID",
metavar="CB_QUERY",
default=None)

ap.add_argument("--config",
Expand Down Expand Up @@ -525,17 +536,30 @@ def main():

elif options.import_query:
try:
query_id = int(options.import_query)
except ValueError:
ap.error("query-id must be an integer")
if query_id < 1:
ap.error("query-id must be a positive")
if isinstance(options.import_query, int):
query = int(options.import_query)
if query < 1:
raise ValueError("query_string must be a positive integer"
"or valid string")
elif isinstance(options.import_query, str):
if options.import_query.startswith("-"):
raise ValueError("query_string must be a positive integer"
"or valid string")
elif options.import_query.isdigit():
query = int(options.import_query)
if query < 1:
raise ValueError("query_string must be a positive integer"
"or valid string")
elif isinstance(options.import_query, str):
query = str(options.import_query)
except ValueError as e:
ap.error(str(e))

try:
if options.import_tagged:
items = import_tagged(mh, cb_config, items_to_import)
elif options.import_query:
items = get_query(mh, cb_config, query_id)
items = get_query(mh, cb_config, query)
except LOBSTER_Error:
return 1

Expand Down
4 changes: 2 additions & 2 deletions packages/lobster-tool-codebeamer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ There are two ways you can use this tool:
1. Download all requirements mentioned by another lobster trace (this
way you do not get a completeness check) (using `--import-tagged`)

2. Download all requirements generated by a saved codebeamer query
(using `--import-query`)
2. Download all requirements generated by a saved codebeamer query ID OR a codebeamer query string (cbQL query)
(using `--import-query` - accepts the query ID as well as query string)

* Configure the 'refs' upstream reference (this argument is optional)
(using `--config`)
Expand Down
100 changes: 99 additions & 1 deletion tests-unit/lobster-codebeamer/test_codebeamer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
from unittest.mock import Mock, patch

from lobster.tools.codebeamer.codebeamer import get_single_item, get_many_items, to_lobster, \
from lobster.tools.codebeamer.codebeamer import get_query, get_single_item, get_many_items, to_lobster, \
import_tagged
from lobster.errors import Message_Handler

Expand All @@ -15,6 +15,104 @@ def _assertListEqualByAttributes(self, list1, list2):
for attr in list_of_compared_attributes:
self.assertEqual(getattr(obj1, attr), getattr(obj2, attr), f"{obj1} is not like {obj2} in {attr}")

@patch('lobster.tools.codebeamer.codebeamer.query_cb_single')
def test_get_query_with_ID(self, mock_query_cb_single):
mh = Message_Handler()
mock_cb_config = {
"root" : "https://codebeamer.bmwgroup.net",
"base": "https://test.com",
"page_size": 10
}
mock_query = 171619121
item_data = [
{
"item": {
"id": 34886222,
"name" : "mock item",
"version": 8,
"tracker": {
"id": 34158092
},
"categories": [{"name": "Requirement"}],
"status": {"name": "Content Review",}
}
}
]
mock_query_cb_single.return_value = {
"page": 1,
"pageSize": 100,
"total": 1,
"items": item_data
}

result = get_query(mh, mock_cb_config, mock_query)
self.assertEqual(len(result), 1)

self.assertEqual(result[0].kind, item_data[0]["item"]["categories"][0]["name"])
self.assertEqual(result[0].status, item_data[0]["item"]["status"]["name"])
self.assertEqual(result[0].name, item_data[0]["item"]["name"])
self.assertEqual(result[0].tag.tag, str(item_data[0]["item"]["id"]))
self.assertEqual(result[0].location.item, item_data[0]["item"]["id"])
self.assertEqual(result[0].location.tracker, item_data[0]["item"]["tracker"]["id"])
self.assertEqual(result[0].location.version, item_data[0]["item"]["version"])

@patch('lobster.tools.codebeamer.codebeamer.query_cb_single')
def test_get_query_with_query(self, mock_query_cb_single):
mh = Message_Handler()
mock_cb_config = {
"root" : "https://codebeamer.bmwgroup.net",
"base": "https://test.com",
"page_size": 10
}
mock_query = "TeamID IN (10833708) AND workItemStatus IN ('InProgress') AND summary LIKE 'Vulnerable Road User'"
item_data = [
{
"id": 34886222,
"name" : "mock item",
"version": 8,
"tracker": {
"id": 34158092
},
"categories": [{"name": "Requirement"}],
"status": {"name": "Content Review",}
}
]
mock_query_cb_single.return_value = {
"page": 1,
"pageSize": 100,
"total": 1,
"items": item_data
}

result = get_query(mh, mock_cb_config, mock_query)
self.assertEqual(len(result), 1)

self.assertEqual(result[0].kind, item_data[0]["categories"][0]["name"])
self.assertEqual(result[0].status, item_data[0]["status"]["name"])
self.assertEqual(result[0].name, item_data[0]["name"])
self.assertEqual(result[0].tag.tag, str(item_data[0]["id"]))
self.assertEqual(result[0].location.item, item_data[0]["id"])
self.assertEqual(result[0].location.tracker, item_data[0]["tracker"]["id"])
self.assertEqual(result[0].location.version, item_data[0]["version"])

@patch('lobster.tools.codebeamer.codebeamer.query_cb_single')
def test_get_query_with_invalid_data(self, mock_query_cb_single):
mock_query = 789
mh = Message_Handler()
mock_cb_config = {
"root" : "https://codebeamer.bmwgroup.net",
"base": "https://test.com",
"page_size": 10
}
mock_query_cb_single.return_value = {
"page": 1,
"pageSize": 100,
"total": 1,
"items": []
}
with self.assertRaises(SystemExit):
get_query(mh, mock_cb_config, mock_query)

@patch('lobster.tools.codebeamer.codebeamer.query_cb_single')
def test_get_single_item(self, mock_get):
_item_id = 11693324
Expand Down

0 comments on commit 7772b7c

Please sign in to comment.