Loading robot2doc/config.py +5 −2 Original line number Diff line number Diff line #!/env/python3 ''' Configurable aspects ''' VERSION = "0.0.4" Loading @@ -25,9 +28,9 @@ DRY_RUN = False # If QUIET is True, output on stdout is minimized QUIET = False # Prefix for the commit URL that may be added after each table. If the GIT_COMMIT # Prefix for the commit URL that may be added after each table. If the GIT_URL_PREFIX # is the empty string, nothing is added. The prefix is concatenated with the filename of # the Robot file. NOTE: if the final slash is not present it will not be included. # Example: # GIT_COMMIT = "http://acme.com/my/example/abcde/" # GIT_URL_PREFIX = "http://acme.com/my/example/abcde/" GIT_URL_PREFIX = "https://forge.etsi.org/rep/nfv/api-tests/raw/" robot2doc/create_sols.py +94 −55 Original line number Diff line number Diff line #!/env/python3 # # Usage: python3 create_sols.py ../../api-tests/ <commit-or-tag> # ''' Generates attachement for TST 010 based on index files in the api-tests repository Usage: python3 create_sols.py <path-to-api-tests> <commit-or-tag> ''' import os import sys Loading @@ -13,16 +15,6 @@ import testspec import config import lib def is_interface_heading(ref): return ref.lvl() == 3 def is_endpoint_heading(ref): return ref.lvl() == 4 def create_test_for_sol(solspec, all_tests_root, commit_id, output_dir): indexes = { "SOL002" : 'sol_002_index.csv', "SOL003" : 'sol_003_index.csv', Loading @@ -41,40 +33,86 @@ def create_test_for_sol(solspec, all_tests_root, commit_id, output_dir): "SOL005" : 'Tests-SOL005-OsMaNfvo.docx', } if not solspec in indexes: print("Error: Wrong SOL Specification: {}".format(solspec)) return def is_interface_heading(ref): '''Check if a reference has heading level 3''' return ref.lvl() == 3 sol_index = None myf = open(indexes[solspec], 'r') sol_index = csv.reader(myf) def is_endpoint_heading(ref): '''Predicate to check if a reference has heading level 4''' return ref.lvl() == 4 def generate_new_clause(row, ref, spec, all_tests_root, commit_id, solspec, current_folder): ''' Generates a new clause, either Void or for a Test Suite (i.e. a .robot file) ''' if "Void" in row["fln"]: lib.generate_void_clause(ref, row["title"], spec, solspec) else: path = os.path.join(all_tests_root, solspec, current_folder, row["fln"]) suite = TestSuiteBuilder().build(path) lib.gen_api_suite(ref, suite, spec, current_folder, commit_id, solspec) def load_spec_index(root_dir, base_spec): ''' Load the index from the file, parses the CSV and applies strip ''' spec_idx = None index_filename = open(os.path.join(root_dir, "indexes", indexes[base_spec]), 'r') spec_idx = csv.DictReader( index_filename, skipinitialspace=True, fieldnames=["ref", "title", "fln"] ) if sol_index is None: print("ERROR OPENING INDEX: {}".format(indexes[solspec])) if spec_idx is None: print("ERROR OPENING INDEX: {}".format(indexes[base_spec])) return [] spec_idx = \ (dict((k, v.strip()) for k, v in row.items() if v) for row in spec_idx if len(row) >= 3) return spec_idx def create_test_for_sol(basedoc, spec_idx, all_tests_root, commit_id, output_dir): ''' Loads index file for a base specification and iterates to produce all clauses, ''' if not basedoc in indexes: print("Error: Wrong SOL Specification: {}".format(basedoc)) return spec = testspec.TestSpec(templates[solspec]) spec = testspec.TestSpec(templates[basedoc]) current_folder = None for row in sol_index: if len(row) < 3: continue ref = lib.DocReference.from_str(row[0].strip()) for item in spec_idx: try: ref = lib.DocReference.from_str(item["ref"]) if is_interface_heading(ref): spec.add_heading_from_ref(row[1].strip(), ref) current_folder = row[2].strip() spec.add_heading_from_ref(item["title"], ref) if "Void" in item["fln"]: spec.add_void_paragraph() else: current_folder = item["fln"] elif is_endpoint_heading(ref): suite = TestSuiteBuilder().build( os.path.join(all_tests_root, solspec, current_folder, row[2].strip()) if item["fln"] is None or current_folder is None: print(item) raise Exception() generate_new_clause( item, ref, spec, all_tests_root, commit_id, basedoc, current_folder ) lib.gen_api_suite(ref, suite, spec, current_folder, commit_id, solspec) outfn = os.path.join(output_dir,outnames[solspec]) print("Writing {} definitions to: {}".format(solspec, outfn)) except Exception as err: print(item, all_tests_root, basedoc, current_folder) raise err outfn = os.path.join(output_dir,outnames[basedoc]) print("Writing {} definitions to: {}".format(basedoc, outfn)) spec.save(outfn) if __name__ == "__main__": Loading @@ -90,8 +128,9 @@ if __name__ == "__main__": print("Generating entire SOL tests") sol_specs = ["SOL002", "SOL003", "SOL005"] sol_specs = ["SOL002"] #, "SOL003", "SOL005"] for solspec in sol_specs: create_test_for_sol(solspec, ROOT, COMMIT_ID, "..") spec_index = load_spec_index(ROOT, solspec) create_test_for_sol(solspec, spec_index, ROOT, COMMIT_ID, "..") robot2doc/lib.py +49 −20 Original line number Diff line number Diff line #!/env/python3 ''' Utilities ''' import os import sys Loading @@ -18,15 +21,14 @@ DRY_RUN = config.DRY_RUN QUIET = config.QUIET BASE_SPEC = config.BASE_SPEC class TestDoc(): def __init__(self, src, doc_fn, doc_main_tit, commit_id, sol, api): self.src = src self.doc_fn = doc_fn self.doc_main_tit = doc_main_tit self.commit_id = commit_id self.sol = sol self.api = api # class TestDoc(): # def __init__(self, src, doc_fn, doc_main_tit, commit_id, sol, api): # self.src = src # self.doc_fn = doc_fn # self.doc_main_tit = doc_main_tit # self.commit_id = commit_id # self.sol = sol # self.api = api class DocReference(): Loading @@ -35,23 +37,28 @@ class DocReference(): self._nums = [int(i) for i in sec_num_list] def lvl(self): '''Returns the level of depth of the reference''' return self._lvl def __str__(self): '''To string''' return ".".join([str(x) for x in self._nums]) def next_ref(self): '''Calculates the next reference and returns it''' nums_cpy = self._nums.copy() nums_cpy[self._lvl - 1] = self._nums[self._lvl - 1] + 1 return DocReference(nums_cpy) def sub_ref(self): '''Return the reference of the first sub-section''' nums_cpy = self._nums.copy() nums_cpy.append(1) return DocReference(nums_cpy) @staticmethod def from_str(string): '''Builds a reference from a string''' return DocReference(string.split(".")) def keyword_to_line(k): Loading @@ -67,16 +74,13 @@ def keywords_to_text(kws): ''' return "\n".join(map(keyword_to_line, kws)) def gen_test(suite, this_test, spec, sec_ref, API, commit_id, sol): def gen_test(this_test, spec, sec_ref, url): ''' Generate the Docx part for an individual test ''' ntp = TP(this_test.doc) log_line = ["++++ TD: ", sol, API, suite, this_test, ntp.tp_id or "No ID"] not QUIET and print(",".join([str(x) for x in log_line])) if DRY_RUN: return if ntp.tp_id is not None: Loading @@ -89,20 +93,34 @@ def gen_test(suite, this_test, spec, sec_ref, API, commit_id, sol): ntp.add_to_spec( spec, keywords_to_text(this_test.keywords), str(suite)+".robot", commit_id, sol, API url ) def generate_void_clause(sec_ref, title, spec, sol): ''' Generates a void clause. Generates Heading and a paragraph with text 'Void.'. ''' print("++ Generating void clause: {} {} {}".format(sol, sec_ref, title)) spec.add_sub_heading_from_ref(str(title), sec_ref, config.DOC_SUITE_LEVEL) spec.add_void_paragraph() def gen_api_suite(sec_ref, suite, spec, workspace, commit_id, sol): ''' Generates all tests in a Robot test suite (i.e .robot file). Generates Heading and a sub clause (heading + test description) for each test in the test suite. ''' print("++ Generating test suite: {} {} {}".format(sol, sec_ref, suite)) spec.add_sub_heading_from_ref(str(suite), sec_ref, config.DOC_SUITE_LEVEL) for i in suite.tests: gen_test(suite, i, spec, sec_ref, workspace, commit_id, sol) url = build_test_url(str(suite)+".robot", commit_id, sol, workspace) def gen_doc(src, doc_fn, doc_main_tit, commit_id, sol, api): log_line = ["++++ TD: ", sol, workspace, suite, i] not QUIET and print(",".join([str(x) for x in log_line])) gen_test(i, spec, sec_ref,url) def gen_doc(src, doc_fn, commit_id, sol): ''' Converts a Robot test suite to a word document Loading Loading @@ -174,3 +192,14 @@ def gen_doc(src, doc_fn, doc_main_tit, commit_id, sol, api): not QUIET and print("Saving to: " + doc_fn) not DRY_RUN and spec.save(doc_fn) not QUIET and print("Finished.") def build_test_url(commit, sol, api, robot_file): '''Builds the URL structure''' configured_prefix = config.GIT_URL_PREFIX if configured_prefix != "": return configured_prefix + commit+"/"+sol+"/"+api+"/"+robot_file return None robot2doc/test_lib.py +29 −1 Original line number Diff line number Diff line ''' Tests for lib.py ''' import lib from robot.api import TestSuiteBuilder from testspec import TestSpec def test_docreference(): ''' Test creation of a TestReference object Loading Loading @@ -52,3 +54,29 @@ def test_subreference(): assert tref.lvl() == 2 assert str(tref) == "1.2" def test_gen_api_suite(): ''' Test generation of a Test Suite (i.e. Robot file) ''' sec_ref = lib.DocReference.from_str("6.4.5.1.1") suite = TestSuiteBuilder().build("../examples/SOL002/VNFConfiguration-API/Configuration.robot") spec = TestSpec("empty.docx") workspace = "Another-API" commit_id = "deadbeef" sol = "SOL002" lib.gen_api_suite( sec_ref, suite, spec, workspace, commit_id, sol ) outfn = "../examples/test.docx" spec.save(outfn) def test_build_test_url(): ''' Tests building the URL to a test ''' url = lib.build_test_url("dead", "SOL002", "My-API", "My-File.robot") assert url == "https://forge.etsi.org/rep/nfv/api-tests/raw/dead/SOL002/My-API/My-File.robot" robot2doc/test_testpurpose.py +28 −10 Original line number Diff line number Diff line Loading @@ -3,31 +3,49 @@ Tests for testpurpose.py ''' import testpurpose from robot.api import TestSuiteBuilder def test_create_tp(): ''' Test creation of a TP object ''' tp_doc = ''' Test ID: X.Y.Z.Y.W\\n\ Title: my title\\n\ tp_doc = ''' Test ID: X.Y.Z.Y.W Title: my title something: more''' tp = testpurpose.TP(tp_doc) ntp = testpurpose.TP(tp_doc) assert(tp.tp_id.strip() == "X.Y.Z.Y.W") assert(len(tp.tp_fields) == 3) assert ntp.tp_id.strip() == "X.Y.Z.Y.W" assert len(ntp.tp_fields) == 3 def test_create_tp_with_no_id(): ''' Test creation of a TP object with no TP object ''' tp_doc = ''' Test suite: My suite\\n\ Title: my title\\n\ tp_doc = ''' Test suite: My suite Title: my title something: more''' tp = testpurpose.TP(tp_doc) ntp = testpurpose.TP(tp_doc) assert ntp.tp_id is None assert len(ntp.tp_fields) == 3 def test_create_tp_sol002_config_test(): ''' Test TP creation for an example test from SOL002 ''' suite = TestSuiteBuilder().build( "../examples/SOL002/VNFConfiguration-API/Configuration.robot" ) ntp = testpurpose.TP(suite.tests[0].doc) assert ntp.tp_id == "6.3.1.1.1" assert ntp.get_field("Test title") == "Set a new VNF Configuration" assert ntp.get_field("Config ID") == "Config_prod_VE" assert ntp.get_field("Post-Conditions") == \ "The configuration is successfully set in the VNF and it matches the issued configuration" assert(tp.tp_id == None) assert(len(tp.tp_fields) == 3) Loading
robot2doc/config.py +5 −2 Original line number Diff line number Diff line #!/env/python3 ''' Configurable aspects ''' VERSION = "0.0.4" Loading @@ -25,9 +28,9 @@ DRY_RUN = False # If QUIET is True, output on stdout is minimized QUIET = False # Prefix for the commit URL that may be added after each table. If the GIT_COMMIT # Prefix for the commit URL that may be added after each table. If the GIT_URL_PREFIX # is the empty string, nothing is added. The prefix is concatenated with the filename of # the Robot file. NOTE: if the final slash is not present it will not be included. # Example: # GIT_COMMIT = "http://acme.com/my/example/abcde/" # GIT_URL_PREFIX = "http://acme.com/my/example/abcde/" GIT_URL_PREFIX = "https://forge.etsi.org/rep/nfv/api-tests/raw/"
robot2doc/create_sols.py +94 −55 Original line number Diff line number Diff line #!/env/python3 # # Usage: python3 create_sols.py ../../api-tests/ <commit-or-tag> # ''' Generates attachement for TST 010 based on index files in the api-tests repository Usage: python3 create_sols.py <path-to-api-tests> <commit-or-tag> ''' import os import sys Loading @@ -13,16 +15,6 @@ import testspec import config import lib def is_interface_heading(ref): return ref.lvl() == 3 def is_endpoint_heading(ref): return ref.lvl() == 4 def create_test_for_sol(solspec, all_tests_root, commit_id, output_dir): indexes = { "SOL002" : 'sol_002_index.csv', "SOL003" : 'sol_003_index.csv', Loading @@ -41,40 +33,86 @@ def create_test_for_sol(solspec, all_tests_root, commit_id, output_dir): "SOL005" : 'Tests-SOL005-OsMaNfvo.docx', } if not solspec in indexes: print("Error: Wrong SOL Specification: {}".format(solspec)) return def is_interface_heading(ref): '''Check if a reference has heading level 3''' return ref.lvl() == 3 sol_index = None myf = open(indexes[solspec], 'r') sol_index = csv.reader(myf) def is_endpoint_heading(ref): '''Predicate to check if a reference has heading level 4''' return ref.lvl() == 4 def generate_new_clause(row, ref, spec, all_tests_root, commit_id, solspec, current_folder): ''' Generates a new clause, either Void or for a Test Suite (i.e. a .robot file) ''' if "Void" in row["fln"]: lib.generate_void_clause(ref, row["title"], spec, solspec) else: path = os.path.join(all_tests_root, solspec, current_folder, row["fln"]) suite = TestSuiteBuilder().build(path) lib.gen_api_suite(ref, suite, spec, current_folder, commit_id, solspec) def load_spec_index(root_dir, base_spec): ''' Load the index from the file, parses the CSV and applies strip ''' spec_idx = None index_filename = open(os.path.join(root_dir, "indexes", indexes[base_spec]), 'r') spec_idx = csv.DictReader( index_filename, skipinitialspace=True, fieldnames=["ref", "title", "fln"] ) if sol_index is None: print("ERROR OPENING INDEX: {}".format(indexes[solspec])) if spec_idx is None: print("ERROR OPENING INDEX: {}".format(indexes[base_spec])) return [] spec_idx = \ (dict((k, v.strip()) for k, v in row.items() if v) for row in spec_idx if len(row) >= 3) return spec_idx def create_test_for_sol(basedoc, spec_idx, all_tests_root, commit_id, output_dir): ''' Loads index file for a base specification and iterates to produce all clauses, ''' if not basedoc in indexes: print("Error: Wrong SOL Specification: {}".format(basedoc)) return spec = testspec.TestSpec(templates[solspec]) spec = testspec.TestSpec(templates[basedoc]) current_folder = None for row in sol_index: if len(row) < 3: continue ref = lib.DocReference.from_str(row[0].strip()) for item in spec_idx: try: ref = lib.DocReference.from_str(item["ref"]) if is_interface_heading(ref): spec.add_heading_from_ref(row[1].strip(), ref) current_folder = row[2].strip() spec.add_heading_from_ref(item["title"], ref) if "Void" in item["fln"]: spec.add_void_paragraph() else: current_folder = item["fln"] elif is_endpoint_heading(ref): suite = TestSuiteBuilder().build( os.path.join(all_tests_root, solspec, current_folder, row[2].strip()) if item["fln"] is None or current_folder is None: print(item) raise Exception() generate_new_clause( item, ref, spec, all_tests_root, commit_id, basedoc, current_folder ) lib.gen_api_suite(ref, suite, spec, current_folder, commit_id, solspec) outfn = os.path.join(output_dir,outnames[solspec]) print("Writing {} definitions to: {}".format(solspec, outfn)) except Exception as err: print(item, all_tests_root, basedoc, current_folder) raise err outfn = os.path.join(output_dir,outnames[basedoc]) print("Writing {} definitions to: {}".format(basedoc, outfn)) spec.save(outfn) if __name__ == "__main__": Loading @@ -90,8 +128,9 @@ if __name__ == "__main__": print("Generating entire SOL tests") sol_specs = ["SOL002", "SOL003", "SOL005"] sol_specs = ["SOL002"] #, "SOL003", "SOL005"] for solspec in sol_specs: create_test_for_sol(solspec, ROOT, COMMIT_ID, "..") spec_index = load_spec_index(ROOT, solspec) create_test_for_sol(solspec, spec_index, ROOT, COMMIT_ID, "..")
robot2doc/lib.py +49 −20 Original line number Diff line number Diff line #!/env/python3 ''' Utilities ''' import os import sys Loading @@ -18,15 +21,14 @@ DRY_RUN = config.DRY_RUN QUIET = config.QUIET BASE_SPEC = config.BASE_SPEC class TestDoc(): def __init__(self, src, doc_fn, doc_main_tit, commit_id, sol, api): self.src = src self.doc_fn = doc_fn self.doc_main_tit = doc_main_tit self.commit_id = commit_id self.sol = sol self.api = api # class TestDoc(): # def __init__(self, src, doc_fn, doc_main_tit, commit_id, sol, api): # self.src = src # self.doc_fn = doc_fn # self.doc_main_tit = doc_main_tit # self.commit_id = commit_id # self.sol = sol # self.api = api class DocReference(): Loading @@ -35,23 +37,28 @@ class DocReference(): self._nums = [int(i) for i in sec_num_list] def lvl(self): '''Returns the level of depth of the reference''' return self._lvl def __str__(self): '''To string''' return ".".join([str(x) for x in self._nums]) def next_ref(self): '''Calculates the next reference and returns it''' nums_cpy = self._nums.copy() nums_cpy[self._lvl - 1] = self._nums[self._lvl - 1] + 1 return DocReference(nums_cpy) def sub_ref(self): '''Return the reference of the first sub-section''' nums_cpy = self._nums.copy() nums_cpy.append(1) return DocReference(nums_cpy) @staticmethod def from_str(string): '''Builds a reference from a string''' return DocReference(string.split(".")) def keyword_to_line(k): Loading @@ -67,16 +74,13 @@ def keywords_to_text(kws): ''' return "\n".join(map(keyword_to_line, kws)) def gen_test(suite, this_test, spec, sec_ref, API, commit_id, sol): def gen_test(this_test, spec, sec_ref, url): ''' Generate the Docx part for an individual test ''' ntp = TP(this_test.doc) log_line = ["++++ TD: ", sol, API, suite, this_test, ntp.tp_id or "No ID"] not QUIET and print(",".join([str(x) for x in log_line])) if DRY_RUN: return if ntp.tp_id is not None: Loading @@ -89,20 +93,34 @@ def gen_test(suite, this_test, spec, sec_ref, API, commit_id, sol): ntp.add_to_spec( spec, keywords_to_text(this_test.keywords), str(suite)+".robot", commit_id, sol, API url ) def generate_void_clause(sec_ref, title, spec, sol): ''' Generates a void clause. Generates Heading and a paragraph with text 'Void.'. ''' print("++ Generating void clause: {} {} {}".format(sol, sec_ref, title)) spec.add_sub_heading_from_ref(str(title), sec_ref, config.DOC_SUITE_LEVEL) spec.add_void_paragraph() def gen_api_suite(sec_ref, suite, spec, workspace, commit_id, sol): ''' Generates all tests in a Robot test suite (i.e .robot file). Generates Heading and a sub clause (heading + test description) for each test in the test suite. ''' print("++ Generating test suite: {} {} {}".format(sol, sec_ref, suite)) spec.add_sub_heading_from_ref(str(suite), sec_ref, config.DOC_SUITE_LEVEL) for i in suite.tests: gen_test(suite, i, spec, sec_ref, workspace, commit_id, sol) url = build_test_url(str(suite)+".robot", commit_id, sol, workspace) def gen_doc(src, doc_fn, doc_main_tit, commit_id, sol, api): log_line = ["++++ TD: ", sol, workspace, suite, i] not QUIET and print(",".join([str(x) for x in log_line])) gen_test(i, spec, sec_ref,url) def gen_doc(src, doc_fn, commit_id, sol): ''' Converts a Robot test suite to a word document Loading Loading @@ -174,3 +192,14 @@ def gen_doc(src, doc_fn, doc_main_tit, commit_id, sol, api): not QUIET and print("Saving to: " + doc_fn) not DRY_RUN and spec.save(doc_fn) not QUIET and print("Finished.") def build_test_url(commit, sol, api, robot_file): '''Builds the URL structure''' configured_prefix = config.GIT_URL_PREFIX if configured_prefix != "": return configured_prefix + commit+"/"+sol+"/"+api+"/"+robot_file return None
robot2doc/test_lib.py +29 −1 Original line number Diff line number Diff line ''' Tests for lib.py ''' import lib from robot.api import TestSuiteBuilder from testspec import TestSpec def test_docreference(): ''' Test creation of a TestReference object Loading Loading @@ -52,3 +54,29 @@ def test_subreference(): assert tref.lvl() == 2 assert str(tref) == "1.2" def test_gen_api_suite(): ''' Test generation of a Test Suite (i.e. Robot file) ''' sec_ref = lib.DocReference.from_str("6.4.5.1.1") suite = TestSuiteBuilder().build("../examples/SOL002/VNFConfiguration-API/Configuration.robot") spec = TestSpec("empty.docx") workspace = "Another-API" commit_id = "deadbeef" sol = "SOL002" lib.gen_api_suite( sec_ref, suite, spec, workspace, commit_id, sol ) outfn = "../examples/test.docx" spec.save(outfn) def test_build_test_url(): ''' Tests building the URL to a test ''' url = lib.build_test_url("dead", "SOL002", "My-API", "My-File.robot") assert url == "https://forge.etsi.org/rep/nfv/api-tests/raw/dead/SOL002/My-API/My-File.robot"
robot2doc/test_testpurpose.py +28 −10 Original line number Diff line number Diff line Loading @@ -3,31 +3,49 @@ Tests for testpurpose.py ''' import testpurpose from robot.api import TestSuiteBuilder def test_create_tp(): ''' Test creation of a TP object ''' tp_doc = ''' Test ID: X.Y.Z.Y.W\\n\ Title: my title\\n\ tp_doc = ''' Test ID: X.Y.Z.Y.W Title: my title something: more''' tp = testpurpose.TP(tp_doc) ntp = testpurpose.TP(tp_doc) assert(tp.tp_id.strip() == "X.Y.Z.Y.W") assert(len(tp.tp_fields) == 3) assert ntp.tp_id.strip() == "X.Y.Z.Y.W" assert len(ntp.tp_fields) == 3 def test_create_tp_with_no_id(): ''' Test creation of a TP object with no TP object ''' tp_doc = ''' Test suite: My suite\\n\ Title: my title\\n\ tp_doc = ''' Test suite: My suite Title: my title something: more''' tp = testpurpose.TP(tp_doc) ntp = testpurpose.TP(tp_doc) assert ntp.tp_id is None assert len(ntp.tp_fields) == 3 def test_create_tp_sol002_config_test(): ''' Test TP creation for an example test from SOL002 ''' suite = TestSuiteBuilder().build( "../examples/SOL002/VNFConfiguration-API/Configuration.robot" ) ntp = testpurpose.TP(suite.tests[0].doc) assert ntp.tp_id == "6.3.1.1.1" assert ntp.get_field("Test title") == "Set a new VNF Configuration" assert ntp.get_field("Config ID") == "Config_prod_VE" assert ntp.get_field("Post-Conditions") == \ "The configuration is successfully set in the VNF and it matches the issued configuration" assert(tp.tp_id == None) assert(len(tp.tp_fields) == 3)