TINKERPOP-1653 Added gremlin.sh test framework Uses python and pexpect to send inputs and test outputs of the Console. Builds with the standard maven process.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/c91bb19a Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/c91bb19a Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/c91bb19a Branch: refs/heads/TINKERPOP-1625 Commit: c91bb19a42f2c0fc6dbc748374c35b9c4d620aa2 Parents: 1503311 Author: Stephen Mallette <sp...@genoprime.com> Authored: Wed Mar 22 16:02:42 2017 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Wed Mar 22 16:02:42 2017 -0400 ---------------------------------------------------------------------- .../developer/development-environment.asciidoc | 8 ++ gremlin-console/pom.xml | 117 +++++++++++++++++++ gremlin-console/src/test/python/setup.cfg | 22 ++++ gremlin-console/src/test/python/setup.py | 36 ++++++ .../src/test/python/tests/__init__.py | 20 ++++ .../src/test/python/tests/test_console.py | 95 +++++++++++++++ gremlin-console/src/test/python/x.groovy | 20 ++++ gremlin-console/src/test/python/y.groovy | 20 ++++ gremlin-console/src/test/python/z.groovy | 20 ++++ 9 files changed, 358 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/docs/src/dev/developer/development-environment.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/dev/developer/development-environment.asciidoc b/docs/src/dev/developer/development-environment.asciidoc index 83cdf38..2508bb7 100644 --- a/docs/src/dev/developer/development-environment.asciidoc +++ b/docs/src/dev/developer/development-environment.asciidoc @@ -77,6 +77,14 @@ which enables the "glv-python" Maven profile or in a more automated fashion simp `gremlin-python` module which will signify to Maven that the environment is Python-ready. The `.glv` file need not have any contents and is ignored by Git. A standard `mvn clean install` will then build `gremlin-python` in full. +As of TinkerPop 3.2.5, the build also requires Python to execute `gremlin-console` integration tests. The integration +test is configured by a "console-integration-tests" Maven profile. This profile can be activated manually or can more +simply piggy-back on the `.glv` file in `gremlin-python`. Note that unlike `gremlin-python` the tests are actually +integration tests and therefore must be actively switched on with `-DskipIntegrationTests=false`: + +[source,text +mvn clean install -pl gremlin-console -DskipIntegrationTests=false + [[release-environment]] Release Environment ~~~~~~~~~~~~~~~~~~~ http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/pom.xml ---------------------------------------------------------------------- diff --git a/gremlin-console/pom.xml b/gremlin-console/pom.xml index ef747c6..08d91a7 100644 --- a/gremlin-console/pom.xml +++ b/gremlin-console/pom.xml @@ -206,4 +206,121 @@ limitations under the License. </plugin> </plugins> </build> + + <profiles> + <!-- activates the building of python components and requires that python be installed on the system. use + the .glv file in gremlin-python as an indicator to activate --> + <profile> + <id>console-integration-tests</id> + <activation> + <activeByDefault>false</activeByDefault> + <file> + <!-- can't use variable here - maven no likey --> + <exists>../gremlin-python/.glv</exists> + </file> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <id>create-python-reports-directory</id> + <phase>initialize</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <skip>${skipIntegrationTests}</skip> + <tasks> + <mkdir dir="${project.build.directory}/python-reports"/> + <mkdir dir="${project.build.directory}/python/env"/> + </tasks> + </configuration> + </execution> + <!-- copy files in python directory to target/python and run virtual env to sandbox python. + there is no need to "activate" the virtualenv because all calls to python occur + directly from bin/ --> + <execution> + <id>setup-py-env</id> + <phase>process-resources</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <skip>${skipIntegrationTests}</skip> + <tasks> + <copy todir="${project.build.directory}/python"> + <fileset dir="src/test/python"/> + </copy> + <exec dir="${project.build.directory}/python" executable="virtualenv" + failonerror="true"> + <arg line="--python=python env"/> + </exec> + </tasks> + </configuration> + </execution> + <execution> + <id>native-python-build</id> + <phase>compile</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <skip>${skipIntegrationTests}</skip> + <target> + <exec executable="env/bin/python" dir="${project.build.directory}/python" + failonerror="true"> + <env key="PYTHONPATH" value=""/> + <arg line="setup.py build --build-lib ${project.build.outputDirectory}/Lib"/> + </exec> + </target> + </configuration> + </execution> + + <execution> + <id>copy-gremlinsh</id> + <phase>pre-integration-test</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <skip>${skipIntegrationTests}</skip> + <tasks> + <copy todir="${project.build.directory}/python/gremlin-console"> + <fileset dir="${project.build.directory}/apache-tinkerpop-gremlin-console-${project.version}-standalone"/> + </copy> + </tasks> + </configuration> + </execution> + + <!-- + use pytest to execute native python tests - output of xunit output is configured in setup.cfg. + must run on integration tests because package phase has to execute to get the console binaries + available for testing + --> + <execution> + <id>native-python-test</id> + <phase>integration-test</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <skip>${skipIntegrationTests}</skip> + <target> + <exec executable="env/bin/python" dir="${project.build.directory}/python" + failonerror="true"> + <env key="PYTHONPATH" value=""/> + <arg line="setup.py test"/> + </exec> + </target> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/setup.cfg ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/setup.cfg b/gremlin-console/src/test/python/setup.cfg new file mode 100644 index 0000000..4d69389 --- /dev/null +++ b/gremlin-console/src/test/python/setup.cfg @@ -0,0 +1,22 @@ +# 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. +[aliases] +test=pytest + +[tool:pytest] +addopts = --junitxml=../python-reports/TEST-native-python.xml +norecursedirs = '.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg' lib lib64 http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/setup.py ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/setup.py b/gremlin-console/src/test/python/setup.py new file mode 100644 index 0000000..a973ae5 --- /dev/null +++ b/gremlin-console/src/test/python/setup.py @@ -0,0 +1,36 @@ +''' +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. +''' +import codecs +import os +import sys +import time +from setuptools import setup + +setup( + name='gremlinconsoletest', + test_suite="tests", + setup_requires=[ + 'pytest-runner', + ], + tests_require=[ + 'pytest', + 'mock', + 'pexpect' + ] +) http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/tests/__init__.py ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/tests/__init__.py b/gremlin-console/src/test/python/tests/__init__.py new file mode 100644 index 0000000..599f5ca --- /dev/null +++ b/gremlin-console/src/test/python/tests/__init__.py @@ -0,0 +1,20 @@ +''' +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. +''' + +__author__ = 'Stephen Mallette (http://stephen.genoprime.com)' \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/tests/test_console.py ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/tests/test_console.py b/gremlin-console/src/test/python/tests/test_console.py new file mode 100644 index 0000000..c2719bd --- /dev/null +++ b/gremlin-console/src/test/python/tests/test_console.py @@ -0,0 +1,95 @@ +''' +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. +''' + +import unittest +from unittest import TestCase +import pexpect + +class TestConsole(TestCase): + + # the base command must pass -C because if colors are enabled pexpect gets garbled input and tests won't pass + gremlinsh = "bash gremlin-console/bin/gremlin.sh -C " + + def test_basic_console_operations(self): + child = pexpect.spawn(TestConsole.gremlinsh) + TestConsole._expect_gremlin_header(child) + TestConsole._send(child, "1-1") + child.expect("==>0\r\n") + TestConsole._expect_prompt(child) + TestConsole._close(child) + + def test_just_dash_i(self): + child = pexpect.spawn(TestConsole.gremlinsh + "-i x.groovy") + TestConsole._expect_gremlin_header(child) + TestConsole._send(child, "x") + child.expect("==>2\r\n") + TestConsole._expect_prompt(child) + TestConsole._close(child) + + def test_dash_i_with_args(self): + child = pexpect.spawn(TestConsole.gremlinsh + "-i y.groovy 1 2 3") + TestConsole._expect_gremlin_header(child) + TestConsole._send(child, "y") + child.expect("==>6\r\n") + TestConsole._expect_prompt(child) + TestConsole._close(child) + + def test_dash_i_multiple_scripts(self): + child = pexpect.spawn(TestConsole.gremlinsh + "-i y.groovy 1 2 3 -i x.groovy -i \"z.groovy x -i --color -D\"") + TestConsole._expect_gremlin_header(child) + TestConsole._send(child, "y") + child.expect("==>6\r\n") + TestConsole._expect_prompt(child) + TestConsole._send(child, "x") + child.expect("==>2\r\n") + TestConsole._expect_prompt(child) + TestConsole._send(child, "z") + child.expect("==>argument=\[x, -i, --color, -D\]\r\n") + TestConsole._expect_prompt(child) + TestConsole._close(child) + + def test_no_mix_dash_i_and_dash_e(self): + child = pexpect.spawn(TestConsole.gremlinsh + "-i y.groovy 1 2 3 -i x.groovy -e \"z.groovy x -i --color -D\"") + child.expect("-i and -e options are mutually exclusive - provide one or the other") + child.expect(pexpect.EOF) + + @staticmethod + def _expect_gremlin_header(child): + # skip/read the Gremlin graphics + child.expect("\r\n") + child.expect(["plugin activated: tinkerpop.server", "plugin activated: tinkerpop.utilities", "plugin activated: tinkerpop.tinkergraph"]) + child.expect(["plugin activated: tinkerpop.server", "plugin activated: tinkerpop.utilities", "plugin activated: tinkerpop.tinkergraph"]) + child.expect(["plugin activated: tinkerpop.server", "plugin activated: tinkerpop.utilities", "plugin activated: tinkerpop.tinkergraph"]) + TestConsole._expect_prompt(child) + + @staticmethod + def _send(child, line): + child.sendline(line) + child.expect(line + "\r\n") + + @staticmethod + def _expect_prompt(child): + child.expect("gremlin> ") + + @staticmethod + def _close(child): + child.sendline(":x") + + + http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/x.groovy ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/x.groovy b/gremlin-console/src/test/python/x.groovy new file mode 100644 index 0000000..31a9f19 --- /dev/null +++ b/gremlin-console/src/test/python/x.groovy @@ -0,0 +1,20 @@ +/* + * 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. + */ + +x = 1 + 1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/y.groovy ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/y.groovy b/gremlin-console/src/test/python/y.groovy new file mode 100644 index 0000000..8b0adf6 --- /dev/null +++ b/gremlin-console/src/test/python/y.groovy @@ -0,0 +1,20 @@ +/* + * 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. + */ + +y = args.collect{Integer.parseInt(it)}.sum() \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c91bb19a/gremlin-console/src/test/python/z.groovy ---------------------------------------------------------------------- diff --git a/gremlin-console/src/test/python/z.groovy b/gremlin-console/src/test/python/z.groovy new file mode 100644 index 0000000..3d7d101 --- /dev/null +++ b/gremlin-console/src/test/python/z.groovy @@ -0,0 +1,20 @@ +/* + * 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. + */ + +z = "argument=" + args \ No newline at end of file