You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/11/15 17:34:19 UTC

[incubator-openwhisk-cli] 08/16: Replace basic runtimes with REST implementation (#2920)

This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 71877f8d040575412f14c25b687a0134fde12840
Author: Vincent <sh...@us.ibm.com>
AuthorDate: Mon Nov 6 15:44:18 2017 -0500

    Replace basic runtimes with REST implementation (#2920)
    
    Swift3, Swift311, Python, Node and Java are not cli related tests.
    We do not have to maintain them as cli test suites, so a straight
    replacement of wsk with wskrest will be sufficient for them.
---
 .../scala/system/basic/WskBasicJavaTests.scala     | 104 +++++++++++++++
 .../scala/system/basic/WskBasicNodeTests.scala     | 140 ++++++++++++++++++++
 .../scala/system/basic/WskBasicPythonTests.scala   | 142 +++++++++++++++++++++
 .../scala/system/basic/WskBasicSwift3Tests.scala   |  65 ++++++++++
 .../scala/system/basic/WskCliBasicJavaTests.scala  |  28 ++++
 .../scala/system/basic/WskCliBasicNodeTests.scala  |  28 ++++
 .../system/basic/WskCliBasicPythonTests.scala      |  28 ++++
 .../system/basic/WskCliBasicSwift311Tests.scala    |  29 +++++
 .../system/basic/WskCliBasicSwift3Tests.scala      |  28 ++++
 .../test/scala/system/basic/WskConsoleTests.scala  |   2 +-
 10 files changed, 593 insertions(+), 1 deletion(-)

diff --git a/tests/src/test/scala/system/basic/WskBasicJavaTests.scala b/tests/src/test/scala/system/basic/WskBasicJavaTests.scala
new file mode 100644
index 0000000..87b38cc
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskBasicJavaTests.scala
@@ -0,0 +1,104 @@
+/*
+ * 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 system.basic
+
+import scala.concurrent.duration.DurationInt
+
+import common.TestHelpers
+import common.TestCLIUtils
+import common.TestUtils.ANY_ERROR_EXIT
+import common.WskTestHelpers
+import common.WskProps
+import common.BaseWsk
+
+import org.junit.runner.RunWith
+import org.scalatest.Matchers
+import org.scalatest.junit.JUnitRunner
+
+import spray.json.JsString
+
+@RunWith(classOf[JUnitRunner])
+abstract class WskBasicJavaTests extends TestHelpers with WskTestHelpers with Matchers {
+
+  implicit val wskprops = WskProps()
+  val wsk: BaseWsk
+  val expectedDuration = 120.seconds
+  val activationPollDuration = 60.seconds
+
+  behavior of "Java Actions"
+
+  /**
+   * Test the Java "hello world" demo sequence
+   */
+  it should "Invoke a java action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "helloJava"
+    val file = Some(TestCLIUtils.getTestActionFilename("helloJava.jar"))
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, main = Some("hello.HelloJava"))
+    }
+
+    val start = System.currentTimeMillis()
+    withActivation(wsk.activation, wsk.action.invoke(name), totalWait = activationPollDuration) {
+      _.response.result.get.toString should include("Hello stranger!")
+    }
+
+    withActivation(
+      wsk.activation,
+      wsk.action.invoke(name, Map("name" -> JsString("Sir"))),
+      totalWait = activationPollDuration) {
+      _.response.result.get.toString should include("Hello Sir!")
+    }
+
+    withClue("Test duration exceeds expectation (ms)") {
+      val duration = System.currentTimeMillis() - start
+      duration should be <= expectedDuration.toMillis
+    }
+  }
+
+  /*
+   * Example from the docs.
+   */
+  it should "Invoke a Java action where main is in the default package" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "helloJavaDefaultPkg"
+      val file = Some(TestCLIUtils.getTestActionFilename("helloJavaDefaultPackage.jar"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, main = Some("Hello"))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name, Map()), totalWait = activationPollDuration) {
+        _.response.result.get.toString should include("Hello stranger!")
+      }
+  }
+
+  it should "Ensure that Java actions cannot be created without a specified main method" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "helloJavaWithNoMainSpecified"
+      val file = Some(TestCLIUtils.getTestActionFilename("helloJava.jar"))
+
+      val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+        action.create(name, file, expectedExitCode = ANY_ERROR_EXIT)
+      }
+
+      val output = s"${createResult.stdout}\n${createResult.stderr}"
+
+      output should include("main")
+  }
+}
diff --git a/tests/src/test/scala/system/basic/WskBasicNodeTests.scala b/tests/src/test/scala/system/basic/WskBasicNodeTests.scala
new file mode 100644
index 0000000..4242c72
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskBasicNodeTests.scala
@@ -0,0 +1,140 @@
+/*
+ * 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 system.basic
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.JsHelpers
+import common.TestHelpers
+import common.TestCLIUtils
+import common.TestUtils.ANY_ERROR_EXIT
+import common.TestUtils.RunResult
+import common.BaseWsk
+import common.WskProps
+import common.WskTestHelpers
+import spray.json._
+import spray.json.DefaultJsonProtocol._
+
+@RunWith(classOf[JUnitRunner])
+abstract class WskBasicNodeTests extends TestHelpers with WskTestHelpers with JsHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk: BaseWsk
+  val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+  val currentNodeJsDefaultKind = "nodejs:6"
+
+  behavior of "NodeJS runtime"
+
+  it should "Map a kind of nodejs:default to the current default NodeJS runtime" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "usingDefaultNodeAlias"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, defaultAction, kind = Some("nodejs:default"))
+      }
+
+      val result = wsk.action.get(name)
+      withPrintOnFailure(result) { () =>
+        val action = convertRunResultToJsObject(result)
+        action.getFieldPath("exec", "kind") should be(Some(currentNodeJsDefaultKind.toJson))
+      }
+  }
+
+  it should "Ensure that NodeJS actions can have a non-default entrypoint" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "niamNpmAction"
+      val file = Some(TestCLIUtils.getTestActionFilename("niam.js"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, main = Some("niam"))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields.get("error") shouldBe empty
+        response.result.get.fields.get("greetings") should be(Some(JsString("Hello from a non-standard entrypoint.")))
+      }
+  }
+
+  it should "Ensure that zipped actions are encoded and uploaded as NodeJS actions" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "zippedNpmAction"
+      val file = Some(TestCLIUtils.getTestActionFilename("zippedaction.zip"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, kind = Some("nodejs:default"))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields.get("error") shouldBe empty
+        response.result.get.fields.get("author") shouldBe defined
+      }
+  }
+
+  it should "Ensure that zipped actions cannot be created without a kind specified" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "zippedNpmActionWithNoKindSpecified"
+      val file = Some(TestCLIUtils.getTestActionFilename("zippedaction.zip"))
+
+      val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+        action.create(name, file, expectedExitCode = ANY_ERROR_EXIT)
+      }
+
+      val output = s"${createResult.stdout}\n${createResult.stderr}"
+
+      output should include("kind")
+  }
+
+  it should "Ensure that JS actions created with no explicit kind use the current default NodeJS runtime" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "jsWithNoKindSpecified"
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, defaultAction)
+    }
+
+    val result = wsk.action.get(name)
+    withPrintOnFailure(result) { () =>
+      val action = convertRunResultToJsObject(result)
+      action.getFieldPath("exec", "kind") should be(Some(currentNodeJsDefaultKind.toJson))
+    }
+  }
+
+  it should "Ensure that returning an empty rejected Promise results in an errored activation" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "jsEmptyRejectPromise"
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("issue-1562.js")))
+    }
+
+    withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+      val response = activation.response
+      response.success should be(false)
+      response.result.get.fields.get("error") shouldBe defined
+    }
+  }
+
+  def convertRunResultToJsObject(result: RunResult): JsObject = {
+    val stdout = result.stdout
+    val firstNewline = stdout.indexOf("\n")
+    stdout.substring(firstNewline + 1).parseJson.asJsObject
+  }
+}
diff --git a/tests/src/test/scala/system/basic/WskBasicPythonTests.scala b/tests/src/test/scala/system/basic/WskBasicPythonTests.scala
new file mode 100644
index 0000000..6cb5861
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskBasicPythonTests.scala
@@ -0,0 +1,142 @@
+/*
+ * 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 system.basic
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import org.scalatest.Matchers
+import scala.concurrent.duration.DurationInt
+import spray.json._
+import spray.json.DefaultJsonProtocol.StringJsonFormat
+import common.JsHelpers
+import common.TestHelpers
+import common.TestCLIUtils
+import common.BaseWsk
+import common.WskProps
+import common.WskTestHelpers
+import common.WhiskProperties
+
+@RunWith(classOf[JUnitRunner])
+abstract class WskBasicPythonTests extends TestHelpers with WskTestHelpers with Matchers with JsHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk: BaseWsk
+
+  behavior of "Native Python Action"
+
+  it should "invoke an action and get the result" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "basicInvoke"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.py")))
+    }
+
+    withActivation(wsk.activation, wsk.action.invoke(name, Map("name" -> "Prince".toJson))) {
+      _.response.result.get.toString should include("Prince")
+    }
+  }
+
+  it should "invoke an action with a non-default entry point" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "nonDefaultEntryPoint"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("niam.py")), main = Some("niam"))
+    }
+
+    withActivation(wsk.activation, wsk.action.invoke(name, Map())) {
+      _.response.result.get.fields.get("greetings") should be(Some(JsString("Hello from a non-standard entrypoint.")))
+    }
+  }
+
+  it should "invoke an action from a zip file with a non-default entry point" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "pythonZipWithNonDefaultEntryPoint"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(
+          name,
+          Some(TestCLIUtils.getTestActionFilename("python.zip")),
+          main = Some("niam"),
+          kind = Some("python:default"))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name, Map("name" -> "Prince".toJson))) {
+        _.response.result.get shouldBe JsObject("greeting" -> JsString("Hello Prince!"))
+      }
+  }
+
+  Seq("python:2", "python:3").foreach { kind =>
+    it should s"invoke a $kind action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+      val name = s"${kind.replace(":", "")}-action"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("pythonVersion.py")), kind = Some(kind))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) {
+        _.response.result.get shouldBe JsObject("version" -> JsNumber(kind.takeRight(1).toInt))
+      }
+    }
+  }
+
+  it should "invoke an action and confirm expected environment is defined" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "stdenv"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("stdenv.py")))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val result = activation.response.result.get
+        result.fields.get("error") shouldBe empty
+        result.fields.get("auth") shouldBe Some(
+          JsString(WhiskProperties.readAuthKey(WhiskProperties.getAuthFileForTesting)))
+        result.fields.get("edge").toString.trim should not be empty
+      }
+  }
+
+  it should "invoke an invalid action and get error back" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "bad code"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("malformed.py")))
+    }
+
+    withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+      activation.response.result.get.fields.get("error") shouldBe Some(
+        JsString("The action failed to generate or locate a binary. See logs for details."))
+      activation.logs.get.mkString("\n") should { not include ("pythonaction.py") and not include ("flask") }
+    }
+  }
+
+  behavior of "Python virtualenv"
+
+  Seq(("python2_virtualenv.zip", "python:2"), ("python3_virtualenv.zip", "python:3")).foreach {
+    case (filename, kind) =>
+      it should s"invoke a zipped $kind action with virtualenv package" in withAssetCleaner(wskprops) {
+        (wp, assetHelper) =>
+          val name = filename
+          val zippedPythonAction = Some(TestCLIUtils.getTestActionFilename(filename))
+
+          assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+            action.create(name, zippedPythonAction, kind = Some(kind))
+          }
+
+          withActivation(wsk.activation, wsk.action.invoke(name), totalWait = 120.seconds) { activation =>
+            val response = activation.response
+            response.result.get.fields.get("error") shouldBe empty
+            response.result.get.fields.get("Networkinfo: ") shouldBe defined
+          }
+      }
+  }
+}
diff --git a/tests/src/test/scala/system/basic/WskBasicSwift3Tests.scala b/tests/src/test/scala/system/basic/WskBasicSwift3Tests.scala
new file mode 100644
index 0000000..77076b4
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskBasicSwift3Tests.scala
@@ -0,0 +1,65 @@
+/*
+ * 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 system.basic
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.JsHelpers
+import common.TestHelpers
+import common.TestCLIUtils
+import common.BaseWsk
+import common.WskProps
+import common.WskTestHelpers
+import spray.json.pimpString
+import spray.json.JsString
+import common.TestUtils.RunResult
+import spray.json.JsObject
+
+@RunWith(classOf[JUnitRunner])
+abstract class WskBasicSwift3Tests extends TestHelpers with WskTestHelpers with JsHelpers {
+
+  implicit val wskprops: common.WskProps = WskProps()
+  val wsk: BaseWsk
+  val defaultAction: Some[String] = Some(TestCLIUtils.getTestActionFilename("hello.swift"))
+  lazy val currentSwiftDefaultKind = "swift:3"
+
+  behavior of "Swift runtime"
+
+  it should "Ensure that Swift actions can have a non-default entrypoint" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "niamSwiftAction"
+      val file = Some(TestCLIUtils.getTestActionFilename("niam.swift"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, main = Some("niam"))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields.get("error") shouldBe empty
+        response.result.get.fields.get("greetings") should be(Some(JsString("Hello from a non-standard entrypoint.")))
+      }
+  }
+
+  def convertRunResultToJsObject(result: RunResult): JsObject = {
+    val stdout = result.stdout
+    val firstNewline = stdout.indexOf("\n")
+    stdout.substring(firstNewline + 1).parseJson.asJsObject
+  }
+}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicJavaTests.scala b/tests/src/test/scala/system/basic/WskCliBasicJavaTests.scala
new file mode 100644
index 0000000..3d26690
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskCliBasicJavaTests.scala
@@ -0,0 +1,28 @@
+/*
+ * 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 system.basic
+
+import common.Wsk
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class WskCliBasicJavaTests extends WskBasicJavaTests {
+  override val wsk: Wsk = new Wsk
+}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicNodeTests.scala b/tests/src/test/scala/system/basic/WskCliBasicNodeTests.scala
new file mode 100644
index 0000000..5c923b9
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskCliBasicNodeTests.scala
@@ -0,0 +1,28 @@
+/*
+ * 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 system.basic
+
+import common.Wsk
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class WskCliBasicNodeTests extends WskBasicNodeTests {
+  override val wsk: Wsk = new Wsk
+}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicPythonTests.scala b/tests/src/test/scala/system/basic/WskCliBasicPythonTests.scala
new file mode 100644
index 0000000..a0957c2
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskCliBasicPythonTests.scala
@@ -0,0 +1,28 @@
+/*
+ * 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 system.basic
+
+import common.Wsk
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class WskCliBasicPythonTests extends WskBasicPythonTests {
+  override val wsk: common.Wsk = new Wsk
+}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicSwift311Tests.scala b/tests/src/test/scala/system/basic/WskCliBasicSwift311Tests.scala
new file mode 100644
index 0000000..017dbd1
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskCliBasicSwift311Tests.scala
@@ -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.
+ */
+
+package system.basic
+
+import common.Wsk
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class WskCliBasicSwift311Tests extends WskBasicSwift3Tests {
+  override val wsk = new Wsk
+  override lazy val currentSwiftDefaultKind: String = "swift:3.1.1"
+}
diff --git a/tests/src/test/scala/system/basic/WskCliBasicSwift3Tests.scala b/tests/src/test/scala/system/basic/WskCliBasicSwift3Tests.scala
new file mode 100644
index 0000000..bbe3cd7
--- /dev/null
+++ b/tests/src/test/scala/system/basic/WskCliBasicSwift3Tests.scala
@@ -0,0 +1,28 @@
+/*
+ * 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 system.basic
+
+import common.Wsk
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class WskCliBasicSwift3Tests extends WskBasicSwift3Tests {
+  override val wsk: common.Wsk = new Wsk
+}
diff --git a/tests/src/test/scala/system/basic/WskConsoleTests.scala b/tests/src/test/scala/system/basic/WskConsoleTests.scala
index 4a00e5d..80aae4d 100644
--- a/tests/src/test/scala/system/basic/WskConsoleTests.scala
+++ b/tests/src/test/scala/system/basic/WskConsoleTests.scala
@@ -42,7 +42,7 @@ import spray.json.pimpAny
 @RunWith(classOf[JUnitRunner])
 abstract class WskConsoleTests extends TestHelpers with WskTestHelpers {
 
-  implicit val wskprops: common.WskProps = WskProps()
+  implicit val wskprops = WskProps()
   val wsk: BaseWsk
   val guestNamespace = wskprops.namespace
 

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.