TINKERPOP-1784 Expanded GLV test framework a bit further Developed methods for vertices/maps and a way to assert unordered results.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9aa198b9 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9aa198b9 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9aa198b9 Branch: refs/heads/TINKERPOP-1784 Commit: 9aa198b92dd929db9244c8094a564da2f6f8b5ac Parents: cda7a5a Author: Stephen Mallette <sp...@genoprime.com> Authored: Fri Sep 22 10:52:20 2017 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Tue Oct 3 14:19:51 2017 -0400 ---------------------------------------------------------------------- gremlin-python/pom.xml | 14 +--- .../src/main/jython/radish/feature_steps.py | 87 ++++++++++++++++---- .../src/main/jython/radish/terrain.py | 11 ++- gremlin-python/src/main/jython/setup.py | 3 +- gremlin-test/features/filter/Coin.feature | 43 ++++++++++ gremlin-test/features/filter/Has.feature | 30 +++++++ gremlin-test/features/map/Coin.feature | 42 ---------- .../features/sideEffect/GroupCount.feature | 29 +++++++ .../step/sideEffect/GroupCountTest.java | 2 +- 9 files changed, 187 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-python/pom.xml ---------------------------------------------------------------------- diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml index 4ab5f37..cabaec9 100644 --- a/gremlin-python/pom.xml +++ b/gremlin-python/pom.xml @@ -339,11 +339,7 @@ limitations under the License. </exec> <exec dir="${project.build.directory}/python2" executable="env/bin/pip" failonerror="true"> - <arg line="install wheel"/> - </exec> - <exec dir="${project.build.directory}/python2" executable="env/bin/pip" - failonerror="true"> - <arg line="install radish-bdd"/> + <arg line="install wheel radish-bdd PyHamcrest"/> </exec> <exec dir="${project.build.directory}/python3" executable="virtualenv" failonerror="true"> @@ -351,11 +347,7 @@ limitations under the License. </exec> <exec dir="${project.build.directory}/python3" executable="env/bin/pip" failonerror="true"> - <arg line="install wheel"/> - </exec> - <exec dir="${project.build.directory}/python3" executable="env/bin/pip" - failonerror="true"> - <arg line="install radish-bdd"/> + <arg line="install wheel radish-bdd PyHamcrest"/> </exec> <exec dir="${project.build.directory}/python-packaged" executable="virtualenv" failonerror="true"> @@ -455,7 +447,7 @@ limitations under the License. <exec executable="env/bin/radish" dir="${project.build.directory}/python2" failonerror="true"> <env key="PYTHONPATH" value=""/> - <arg line="-b ${project.build.directory}/python2/radish ${project.basedir}/../gremlin-test/features/"/> + <arg line="-b ${project.build.directory}/python2/radish ${project.basedir}/../gremlin-test/features/"/> <!-- -no-line-jump --> </exec> </target> </configuration> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-python/src/main/jython/radish/feature_steps.py ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/jython/radish/feature_steps.py b/gremlin-python/src/main/jython/radish/feature_steps.py index 61297ff..069768d 100644 --- a/gremlin-python/src/main/jython/radish/feature_steps.py +++ b/gremlin-python/src/main/jython/radish/feature_steps.py @@ -17,24 +17,36 @@ specific language governing permissions and limitations under the License. ''' -from gremlin_python.structure.graph import Graph +import json +from gremlin_python.structure.graph import Graph, Vertex, Edge from gremlin_python.process.graph_traversal import __ -from gremlin_python.process.traversal import Scope -from radish import before, given, when, then +from gremlin_python.process.traversal import P, Scope +from radish import given, when, then, custom_type, register_custom_type, TypeBuilder +from hamcrest import * out = __.out -@given("the {graphName:w} graph") -def choose_graph(step, graphName): +@custom_type('words', r'\w+') +def parse_word(text): + return str(text) + + +register_custom_type(WordList=TypeBuilder.with_many(parse_word, listsep=',')) + + +@given("the {graph_name:w} graph") +def choose_graph(step, graph_name): # only have modern atm but graphName would be used to select the right one - step.context.g = Graph().traversal().withRemote(step.context.remote_conn_modern) + step.context.g = Graph().traversal().withRemote(step.context.remote_conn[graph_name]) @given("the traversal of") def translate_traversal(step): g = step.context.g - step.context.traversal = eval(step.text, {"g": g, "Scope": Scope}) + step.context.traversal = eval(step.text, {"g": g, + "P": P, + "Scope": Scope}) @when("iterated to list") @@ -45,33 +57,74 @@ def iterate_the_traversal(step): @then("the result should be {characterized_as:w}") def assert_result(step, characterized_as): if characterized_as == "empty": - assert len(step.context.result) == 0 + assert_that(len(step.context.result), equal_to(0)) elif characterized_as == "ordered": data = step.table # results from traversal should have the same number of entries as the feature data table - assert len(step.context.result) == len(data) + assert_that(len(step.context.result), equal_to(len(data))) # assert the results by type where the first column will hold the type and the second column # the data to assert. the contents of the second column will be dependent on the type specified - # in te first column + # in the first column for ix, line in enumerate(data): if line[0] == "numeric": - assert long(step.context.result[ix]) == long(line[1]) + assert_that(long(step.context.result[ix]), equal_to(long(line[1]))) elif line[0] == "string": - assert str(step.context.result[ix]) == str(line[1]) + assert_that(str(step.context.result[ix]), equal_to(str(line[1]))) + elif line[0] == "vertex": + assert_that(step.context.result[ix].label, equal_to(line[1])) + elif line[0] == "map": + assert_that(step.context.result[ix], json.loads(line[1])) else: - assert step.context.result[ix] == line[1] + raise ValueError("unknown type of " + line[0]) elif characterized_as == "unordered": data = step.table # results from traversal should have the same number of entries as the feature data table - assert len(step.context.result) == len(data) + assert_that(len(step.context.result), equal_to(len(data))) + + results_to_test = list(step.context.result) + + for line in data: + if line[0] == "numeric": + val = long(line[1]) + assert_that(val, is_in(list(map(long, results_to_test)))) + results_to_test.remove(val) + elif line[0] == "string": + val = str(line[1]) + assert_that(val, is_in(list(map(str, results_to_test)))) + results_to_test.remove(val) + elif line[0] == "vertex": + val = str(line[1]) + v = step.context.lookup["modern"][val] + assert_that(v, is_in(results_to_test)) + results_to_test.remove(v) + elif line[0] == "map": + val = json.load(line[1]) + assert_that(val, is_in(results_to_test)) + results_to_test.remove(val) + else: + raise ValueError("unknown type of " + line[0]) + + assert_that(len(results_to_test), is_(0)) + else: + raise ValueError("unknown data characterization of " + characterized_as) +@then("the number of results should be {number:d}") +def assert_number_of_results(step, number): + assert_that(len(step.context.result), equal_to(number)) -@then("the results should be empty") -def assert_result(step): - assert len(step.context.result) == 0 +@then("the results should all be {element_type:w}") +def assert_elements(step, element_type): + if element_type == "vertices": + t = Vertex + elif element_type == "edges": + t = Edge + else: + raise ValueError("unknown element type of " + element_type) + for r in step.context.result: + assert_that(r, instance_of(t)) http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-python/src/main/jython/radish/terrain.py ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/jython/radish/terrain.py b/gremlin-python/src/main/jython/radish/terrain.py index 389f39c..59ec8d0 100644 --- a/gremlin-python/src/main/jython/radish/terrain.py +++ b/gremlin-python/src/main/jython/radish/terrain.py @@ -17,15 +17,22 @@ specific language governing permissions and limitations under the License. ''' +from gremlin_python.structure.graph import Graph +from gremlin_python.process.graph_traversal import __ from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection from radish import before, after @before.each_scenario def prepare_traversal_source(scenario): - scenario.context.remote_conn_modern = DriverRemoteConnection('ws://localhost:45940/gremlin', 'g') + remote = DriverRemoteConnection('ws://localhost:45940/gremlin', 'g') + scenario.context.remote_conn = {"modern": remote} + g = Graph().traversal().withRemote(remote) + + # hold a map of name/vertex for use in asserting results + scenario.context.lookup = {"modern": g.V().group().by('name').by(__.tail()).next()} @after.each_scenario def close_traversal_source(scenario): - scenario.context.remote_conn_modern.close() + scenario.context.remote_conn["modern"].close() http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-python/src/main/jython/setup.py ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/jython/setup.py b/gremlin-python/src/main/jython/setup.py index fddd7c8..4498e5b 100644 --- a/gremlin-python/src/main/jython/setup.py +++ b/gremlin-python/src/main/jython/setup.py @@ -71,7 +71,8 @@ setup( tests_require=[ 'pytest', 'mock', - 'radish-bdd' + 'radish-bdd', + 'PyHamcrest' ], install_requires=install_requires, classifiers=[ http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-test/features/filter/Coin.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/filter/Coin.feature b/gremlin-test/features/filter/Coin.feature new file mode 100644 index 0000000..1b88f58 --- /dev/null +++ b/gremlin-test/features/filter/Coin.feature @@ -0,0 +1,43 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +Feature: Step - coin() + + Scenario: Use coin at 1.0 + Given the modern graph + And the traversal of + """ + g.V().coin(1.0) + """ + When iterated to list + Then the result should be unordered + | vertex | marko | + | vertex | vadas | + | vertex | lop | + | vertex | josh | + | vertex | ripple | + | vertex | peter | + + + Scenario: Use coin at 0.0 + Given the modern graph + And the traversal of + """ + g.V().coin(0.0) + """ + When iterated to list + Then the result should be empty \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-test/features/filter/Has.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/filter/Has.feature b/gremlin-test/features/filter/Has.feature new file mode 100644 index 0000000..0bb82e0 --- /dev/null +++ b/gremlin-test/features/filter/Has.feature @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +Feature: Step - has() + + Scenario: Use has() with P.gt() + Given the modern graph + And the traversal of + """ + g.V().has("age", P.gt(30)) + """ + When iterated to list + Then the result should be unordered + | vertex | josh | + | vertex | peter | + http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-test/features/map/Coin.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/map/Coin.feature b/gremlin-test/features/map/Coin.feature deleted file mode 100644 index b21bd70..0000000 --- a/gremlin-test/features/map/Coin.feature +++ /dev/null @@ -1,42 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -Feature: Step - coin() - - Scenario: Use coin at 1.0 - Given the modern graph - And the traversal of - """ - g.V().coin(1.0) - """ - When iterated to list - Then the result should be unordered as - | vertex | person | - | vertex | person | - | vertex | person | - | vertex | person | - | vertex | software | - | vertex | software | - - Scenario: Use coin at 0.0 - Given the modern graph - And the traversal of - """ - g.V().coin(0.0) - """ - When iterated to list - Then the result should be empty \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-test/features/sideEffect/GroupCount.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/sideEffect/GroupCount.feature b/gremlin-test/features/sideEffect/GroupCount.feature new file mode 100644 index 0000000..1789b32 --- /dev/null +++ b/gremlin-test/features/sideEffect/GroupCount.feature @@ -0,0 +1,29 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +Feature: Step - groupCount() + + Scenario: Use has() with P.gt() + Given the modern graph + And the traversal of + """ + g.V().out("created").groupCount().by("name") + """ + When iterated to list + Then the result should be ordered + | map | {"ripple": 1, "lop": 3} | + http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9aa198b9/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountTest.java index 9bd515c..34011ac 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountTest.java @@ -94,7 +94,7 @@ public abstract class GroupCountTest extends AbstractGremlinProcessTest { checkSideEffects(traversal.asAdmin().getSideEffects(), "a", HashMap.class); } - private static void assertCommonA(Traversal<Vertex, Map<String, Long>> traversal) { + private static void assertCommonA(final Traversal<Vertex, Map<String, Long>> traversal) { final Map<String, Long> map = traversal.next(); assertEquals(map.size(), 2); assertEquals(Long.valueOf(3l), map.get("lop"));