TINKERPOP-1784 Completed the VertexTest cases
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/4983fe40 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/4983fe40 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/4983fe40 Branch: refs/heads/TINKERPOP-1784 Commit: 4983fe4039ef7242df637fd3e7b9513c84954797 Parents: b0423f5 Author: Stephen Mallette <[email protected]> Authored: Fri Sep 29 15:44:50 2017 -0400 Committer: Stephen Mallette <[email protected]> Committed: Mon Oct 16 11:19:30 2017 -0400 ---------------------------------------------------------------------- .../src/main/jython/radish/feature_steps.py | 18 +- gremlin-test/features/map/Vertex.feature | 226 ++++++++++++++++--- .../gremlin/process/FeatureCoverageTest.java | 93 ++++++++ .../gremlin/structure/FeatureCoverageTest.java | 92 -------- 4 files changed, 305 insertions(+), 124 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4983fe40/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 a298d6c..340f84a 100644 --- a/gremlin-python/src/main/jython/radish/feature_steps.py +++ b/gremlin-python/src/main/jython/radish/feature_steps.py @@ -21,7 +21,7 @@ import json import re from gremlin_python.structure.graph import Graph from gremlin_python.process.graph_traversal import __ -from gremlin_python.process.traversal import P, Scope, Column +from gremlin_python.process.traversal import P, Scope, Column, Direction from radish import given, when, then from hamcrest import * @@ -35,6 +35,12 @@ def choose_graph(step, graph_name): step.context.g = Graph().traversal().withRemote(step.context.remote_conn[graph_name]) +@given("an unsupported test") +def unsupported_scenario(step): + # this is a do nothing step as the test can't be supported for whatever reason + return + + @given("using the parameter {param_name:w} is {param:QuotedString}") def add_parameter(step, param_name, param): if not hasattr(step.context, "traversal_params"): @@ -48,6 +54,7 @@ def translate_traversal(step): g = step.context.g b = {"g": g, "Column": Column, + "Direction": Direction, "P": P, "Scope": Scope, "bothE": __.bothE} @@ -75,6 +82,11 @@ def assert_result(step, characterized_as): raise ValueError("unknown data characterization of " + characterized_as) +@then("nothing should happen") +def nothing_happening(step): + return + + def __convert(val, ctx): if isinstance(val, dict): # convert dictionary keys/values n = {} @@ -89,10 +101,14 @@ def __convert(val, ctx): return long(val[2:-1]) elif isinstance(val, str) and re.match("^v\[.*\]\.id$", val): # parse vertex id return ctx.lookup_v["modern"][val[2:-4]].id + elif isinstance(val, str) and re.match("^v\[.*\]\.sid$", val): # parse vertex id as string + return ctx.lookup_v["modern"][val[2:-5]].id elif isinstance(val, str) and re.match("^v\[.*\]$", val): # parse vertex return ctx.lookup_v["modern"][val[2:-1]] elif isinstance(val, str) and re.match("^e\[.*\]\.id$", val): # parse edge id return ctx.lookup_e["modern"][val[2:-4]].id + elif isinstance(val, str) and re.match("^e\[.*\]\.sid$", val): # parse edge id as string + return ctx.lookup_e["modern"][val[2:-5]].id elif isinstance(val, str) and re.match("^e\[.*\]$", val): # parse edge return ctx.lookup_e["modern"][val[2:-1]] elif isinstance(val, str) and re.match("^m\[.*\]$", val): # parse json as a map http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4983fe40/gremlin-test/features/map/Vertex.feature ---------------------------------------------------------------------- diff --git a/gremlin-test/features/map/Vertex.feature b/gremlin-test/features/map/Vertex.feature index 1905f3a..37e398b 100644 --- a/gremlin-test/features/map/Vertex.feature +++ b/gremlin-test/features/map/Vertex.feature @@ -19,7 +19,7 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VXlistX1_2_3XX_name Given the modern graph - And using the parameter vx is "l[v[marko],v[vadas],v[lop]]" + And using the parameter vx is "l[v[marko].id,v[vadas].id,v[lop].id]" And the traversal of """ g.V(vx).values("name") @@ -32,7 +32,7 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VXlistXv1_v2_v3XX_name Given the modern graph - And using the parameter vx is "l[v[marko].id,v[vadas].id,v[lop].id]" + And using the parameter vx is "l[v[marko],v[vadas],v[lop]]" And the traversal of """ g.V(vx).values("name") @@ -60,10 +60,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX1X_out Given the modern graph - And using the parameter v1 is "v[marko]" + And using the parameter v1Id is "v[marko].id" And the traversal of """ - g.V(v1).out() + g.V(v1Id).out() """ When iterated to list Then the result should be unordered @@ -73,10 +73,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX2X_in Given the modern graph - And using the parameter v2 is "v[vadas]" + And using the parameter v2Id is "v[vadas].id" And the traversal of """ - g.V(v2).in() + g.V(v2Id).in() """ When iterated to list Then the result should be unordered @@ -84,10 +84,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX4X_both Given the modern graph - And using the parameter v4 is "v[josh]" + And using the parameter v4Id is "v[josh].id" And the traversal of """ - g.V(v4).both() + g.V(v4Id).both() """ When iterated to list Then the result should be unordered @@ -112,10 +112,21 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_EX11X Given the modern graph - And using the parameter e11 is "e[josh-created->lop]" + And using the parameter e11Id is "e[josh-created->lop].id" + And the traversal of + """ + g.E(e11Id) + """ + When iterated to list + Then the result should be unordered + | e[josh-created->lop] | + + Scenario: g_EX11AsStringX + Given the modern graph + And using the parameter e11Id is "e[josh-created->lop].sid" And the traversal of """ - g.E(e11) + g.E(e11Id) """ When iterated to list Then the result should be unordered @@ -123,10 +134,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX1X_outE Given the modern graph - And using the parameter v1 is "v[marko]" + And using the parameter v1Id is "v[marko].id" And the traversal of """ - g.V(v1).outE() + g.V(v1Id).outE() """ When iterated to list Then the result should be unordered @@ -136,10 +147,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX2X_outE Given the modern graph - And using the parameter v2 is "v[vadas]" + And using the parameter v2Id is "v[vadas].id" And the traversal of """ - g.V(v2).inE() + g.V(v2Id).inE() """ When iterated to list Then the result should be unordered @@ -147,10 +158,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX4X_bothEXcreatedX Given the modern graph - And using the parameter v4 is "v[josh]" + And using the parameter v4Id is "v[josh].id" And the traversal of """ - g.V(v4).bothE("created") + g.V(v4Id).bothE("created") """ When iterated to list Then the result should be unordered @@ -159,10 +170,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX4X_bothE Given the modern graph - And using the parameter v4 is "v[josh]" + And using the parameter v4Id is "v[josh].id" And the traversal of """ - g.V(v4).bothE() + g.V(v4Id).bothE() """ When iterated to list Then the result should be unordered @@ -172,10 +183,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX1X_outE_inV Given the modern graph - And using the parameter v1 is "v[marko]" + And using the parameter v1Id is "v[marko].id" And the traversal of """ - g.V(v1).both() + g.V(v1Id).both() """ When iterated to list Then the result should be unordered @@ -185,10 +196,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX2X_inE_outV Given the modern graph - And using the parameter v2 is "v[vadas]" + And using the parameter v2Id is "v[vadas].id" And the traversal of """ - g.V(v2).inE().outV() + g.V(v2Id).inE().outV() """ When iterated to list Then the result should be unordered @@ -226,10 +237,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX1X_outEXknowsX_bothV_name Given the modern graph - And using the parameter v1 is "v[marko]" + And using the parameter v1Id is "v[marko].id" And the traversal of """ - g.V(v1).outE("knows").bothV().values("name") + g.V(v1Id).outE("knows").bothV().values("name") """ When iterated to list Then the result should be unordered @@ -240,10 +251,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX1X_outE_otherV Given the modern graph - And using the parameter v1 is "v[marko]" + And using the parameter v1Id is "v[marko].id" And the traversal of """ - g.V(v1).outE().otherV() + g.V(v1Id).outE().otherV() """ When iterated to list Then the result should be unordered @@ -253,10 +264,10 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX4X_bothE_otherV Given the modern graph - And using the parameter v4 is "v[josh]" + And using the parameter v4Id is "v[josh].id" And the traversal of """ - g.V(v4).bothE().otherV() + g.V(v4Id).bothE().otherV() """ When iterated to list Then the result should be unordered @@ -266,11 +277,164 @@ Feature: Step - V(), E(), out(), in(), both(), inE(), outE(), bothE() Scenario: g_VX4X_bothE_hasXweight_lt_1X_otherV Given the modern graph - And using the parameter v4 is "v[josh]" + And using the parameter v4Id is "v[josh].id" + And the traversal of + """ + g.V(v4Id).bothE().has("weight", P.lt(1.0)).otherV() + """ + When iterated to list + Then the result should be unordered + | v[lop] | + + Scenario: g_VX2X_inE + Given the modern graph + And using the parameter v2Id is "v[vadas].id" + And the traversal of + """ + g.V(v2Id).bothE() + """ + When iterated to list + Then the result should be unordered + | e[marko-knows->vadas] | + + Scenario: get_g_VX1X_outE_otherV + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).outE().otherV() + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + | v[lop] | + + Scenario: g_VX1X_outXknowsX + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).out("knows") + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + + Scenario: g_VX1AsStringX_outXknowsX + Given the modern graph + And using the parameter v1Id is "v[marko].sid" And the traversal of """ - g.V(v4).bothE().has("weight", P.lt(1.0)).otherV() + g.V(v1Id).out("knows") """ When iterated to list Then the result should be unordered - | v[lop] | \ No newline at end of file + | v[vadas] | + | v[josh] | + + Scenario: g_VX1X_outXknows_createdX + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).out("knows","created") + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + | v[lop] | + + Scenario: g_VX1X_outEXknowsX_inV + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).outE("knows").inV() + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + + Scenario: g_VX1X_outEXknows_createdX_inV + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).outE("knows","created").inV() + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + | v[lop] | + + Scenario: g_V_out_out + Given the modern graph + And the traversal of + """ + g.V().out().out() + """ + When iterated to list + Then the result should be unordered + | v[ripple] | + | v[lop] | + + Scenario: g_VX1X_out_out_out + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).out().out().out() + """ + When iterated to list + Then the result should be empty + + Scenario: g_VX1X_out_name + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).out().values("name") + """ + When iterated to list + Then the result should be unordered + | vadas | + | josh | + | lop | + + Scenario: g_VX1X_to_XOUT_knowsX + Given the modern graph + And using the parameter v1Id is "v[marko].id" + And the traversal of + """ + g.V(v1Id).to(Direction.OUT, "knows") + """ + When iterated to list + Then the result should be unordered + | v[vadas] | + | v[josh] | + + Scenario: g_VX1_2_3_4X_name + Given an unsupported test + Then nothing should happen + + Scenario: g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name + Given the modern graph + And the traversal of + """ + g.V().hasLabel("person").V().hasLabel("software").values("name") + """ + When iterated to list + Then the result should be unordered + | lop | + | lop | + | lop | + | lop | + | ripple | + | ripple | + | ripple | + | ripple | \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4983fe40/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/process/FeatureCoverageTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/process/FeatureCoverageTest.java b/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/process/FeatureCoverageTest.java new file mode 100644 index 0000000..d3212a4 --- /dev/null +++ b/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/process/FeatureCoverageTest.java @@ -0,0 +1,93 @@ +/* + * 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. + */ +package org.apache.tinkerpop.gremlin.process; + +import org.apache.tinkerpop.gremlin.process.traversal.step.filter.CoinTest; +import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexTest; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class FeatureCoverageTest { + + private static Pattern scenarioName = Pattern.compile("^\\s*Scenario:\\s*(.*)$"); + + @Test + public void shouldImplementAllProcessTestsAsFeatures() throws Exception { + + // TEMPORARY while test framework is under development - all tests should ultimately be included + final List<Class<?>> temp = Arrays.asList(CoinTest.class, VertexTest.class); + + final Field field = ProcessStandardSuite.class.getDeclaredField("testsToEnforce"); + field.setAccessible(true); + final Class<?>[] testsToEnforce = (Class<?>[]) field.get(null); + + final List<Class<?>> testClassesToEnforce = Stream.of(testsToEnforce).filter(temp::contains).collect(Collectors.toList()); + for (Class<?> t : testClassesToEnforce) { + final String packge = t.getPackage().getName(); + final String group = packge.substring(packge.lastIndexOf(".") + 1, packge.length()); + final String featureFileName = "features" + File.separator + + group + File.separator + + t.getSimpleName().replace("Test", "") + ".feature"; + final Set<String> testMethods = Stream.of(t.getDeclaredMethods()) + .filter(m -> m.isAnnotationPresent(Test.class)) + .map(Method::getName).collect(Collectors.toSet()); + + final File featureFile = new File(featureFileName); + assertThat(featureFile.exists(), is(true)); + assertThat(featureFile.isFile(), is(true)); + + final Set<String> testsInFeatureFile = new HashSet<>(); + final InputStream is = new FileInputStream(featureFile); + final BufferedReader buf = new BufferedReader(new InputStreamReader(is)); + String line = buf.readLine(); + while(line != null){ + final Matcher matcher = scenarioName.matcher(line); + if (matcher.matches()) + testsInFeatureFile.add(matcher.group(1)); + line = buf.readLine(); + } + + testMethods.removeAll(testsInFeatureFile); + + assertEquals("All test methods are not implemented in the " + featureFileName + ": " + testMethods, testMethods.size(), 0); + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4983fe40/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/structure/FeatureCoverageTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/structure/FeatureCoverageTest.java b/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/structure/FeatureCoverageTest.java deleted file mode 100644 index 791d44e..0000000 --- a/gremlin-test/src/test/java/org/apache/tinkerpop/gremlin/structure/FeatureCoverageTest.java +++ /dev/null @@ -1,92 +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. - */ -package org.apache.tinkerpop.gremlin.structure; - -import org.apache.tinkerpop.gremlin.process.ProcessStandardSuite; -import org.apache.tinkerpop.gremlin.process.traversal.step.filter.CoinTest; -import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountTest; -import org.junit.Test; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -/** - * @author Stephen Mallette (http://stephen.genoprime.com) - */ -public class FeatureCoverageTest { - - private static Pattern scenarioName = Pattern.compile("^\\s*Scenario:\\s*(.*)$"); - - @Test - public void shouldImplementAllProcessTestsAsFeatures() throws Exception { - - // TEMPORARY while test framework is under development - all tests should ultimately be included - final List<Class<?>> temp = Arrays.asList(CoinTest.class); - - final Field field = ProcessStandardSuite.class.getDeclaredField("testsToEnforce"); - field.setAccessible(true); - final Class<?>[] testsToEnforce = (Class<?>[]) field.get(null); - - final List<Class<?>> testClassesToEnforce = Stream.of(testsToEnforce).filter(temp::contains).collect(Collectors.toList()); - for (Class<?> t : testClassesToEnforce) { - final String packge = t.getPackage().getName(); - final String group = packge.substring(packge.lastIndexOf(".") + 1, packge.length()); - final String featureFileName = "features" + File.separator + - group + File.separator + - t.getSimpleName().replace("Test", "") + ".feature"; - final Set<String> testMethods = Stream.of(t.getDeclaredMethods()) - .filter(m -> m.isAnnotationPresent(Test.class)) - .map(Method::getName).collect(Collectors.toSet()); - - final File featureFile = new File(featureFileName); - assertThat(featureFile.exists(), is(true)); - assertThat(featureFile.isFile(), is(true)); - - final Set<String> testsInFeatureFile = new HashSet<>(); - final InputStream is = new FileInputStream(featureFile); - final BufferedReader buf = new BufferedReader(new InputStreamReader(is)); - String line = buf.readLine(); - while(line != null){ - final Matcher matcher = scenarioName.matcher(line); - if (matcher.matches()) - testsInFeatureFile.add(matcher.group(1)); - line = buf.readLine(); - } - - assertEquals("All test methods are not implemented in the " + featureFileName, testMethods, testsInFeatureFile); - } - } -}
