PY-13758 BDD: allow to run several feature files in one run configuration
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Wed, 3 Sep 2014 17:59:56 +0000 (21:59 +0400)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Wed, 3 Sep 2014 17:59:56 +0000 (21:59 +0400)
platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java
python/helpers/pycharm/_bdd_utils.py
python/helpers/pycharm/behave_runner.py
python/helpers/pycharm/lettuce_runner.py

index 909c44db199b76b88f5c2384609d7a2ee567b499..cd5e8630a0874ee97914a8ea72cd6cbb5ef13a38 100644 (file)
@@ -22,7 +22,10 @@ import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 public class JDOMExternalizer {
   private JDOMExternalizer() {
@@ -66,7 +69,7 @@ public class JDOMExternalizer {
     return null;
   }
 
-  public static void writeMap(Element root, Map<String, String>map, @NonNls @Nullable String rootName, @NonNls String entryName) {
+  public static void writeMap(Element root, Map<String, String> map, @NonNls @Nullable String rootName, @NonNls String entryName) {
     Element mapRoot;
     if (StringUtil.isNotEmpty(rootName)) {
       mapRoot = new Element(rootName);
@@ -106,6 +109,26 @@ public class JDOMExternalizer {
     }
   }
 
+  /**
+   * Saves a pack of strings to some attribte. I.e: [tag attr="value"]
+   * @param parent parent element (where to add newly created tags)
+   * @param nodeName node name (tag, in our example)
+   * @param attrName attribute name (attr, in our example)
+   * @param values a pack of values to add
+   * @see #loadStringsList(org.jdom.Element, String, String)
+   */
+  public static void saveStringsList(@NotNull final Element parent,
+                                     @NotNull final String nodeName,
+                                     @NotNull final String attrName,
+                                     @NotNull final String... values) {
+    for (final String value : values) {
+      final Element node = new Element(nodeName);
+      node.setAttribute(attrName, value);
+      parent.addContent(node);
+    }
+  }
+
+  @NotNull
   public static List<String> loadStringsList(Element element, String rootName, String attrName) {
     final List<String> paths = new LinkedList<String>();
     if (element != null) {
index eea1bebf16546a1a8d9a2b0b886b6342261c9b9b..9eb90681e1276b01b57f3acdf40a94597219f366 100644 (file)
@@ -29,19 +29,27 @@ def fix_win_drive(feature_path):
         os.chdir(feature_disk)
 
 
-def get_path_by_args(arguments):
+def get_path_by_env(environment):
     """
-    :type arguments list
-    :param arguments: arguments (sys.argv)
-    :return: tuple (base_dir, what_to_run) where dir is current or first argument from argv, checking it exists
-    :rtype tuple of str
+    :type environment dict
+    :param environment: os.environment (files and folders should be separated with | and passed to PY_STUFF_TO_RUN)
+    :return: tuple (base_dir, what_to_run(list of feature files or folders))) where dir is current or first argument from env, checking it exists
+    :rtype tuple of (str, iterable)
     """
-    what_to_run = arguments[1] if len(arguments) > 1 else "."
-    base_dir = what_to_run
-    assert os.path.exists(what_to_run), "{} does not exist".format(what_to_run)
+    if "PY_STUFF_TO_RUN" not in environment:
+        what_to_run = ["."]
+    else:
+        what_to_run = str(environment["PY_STUFF_TO_RUN"]).split("|")
 
-    if os.path.isfile(what_to_run):
-        base_dir = os.path.dirname(what_to_run)  # User may point to the file directly
+    if not what_to_run:
+        what_to_run = ["."]
+
+    for path in what_to_run:
+        assert os.path.exists(path), "{} does not exist".format(path)
+
+    base_dir = what_to_run[0]
+    if os.path.isfile(what_to_run[0]):
+        base_dir = os.path.dirname(what_to_run[0])  # User may point to the file directly
     return base_dir, what_to_run
 
 
index 2ec649ea7c1d7de07279052f10227d2af9d2eddb..51171530ddb4039bcb4e3d60094bba4a215ee98e 100644 (file)
@@ -1,13 +1,14 @@
 # coding=utf-8
 """
 Behave BDD runner.
-*FIRST* param now: folder to search "features" for.
-Each "features" folder should have features and "steps" subdir.
+See _bdd_utils#get_path_by_env for information how to pass list of features here.
+Each feature could be file, folder with feature files or folder with "features" subfolder
 
 Other args are tag expressionsin format (--tags=.. --tags=..).
 See https://pythonhosted.org/behave/behave.html#tag-expression
 """
 import functools
+import glob
 import sys
 import os
 import traceback
@@ -236,12 +237,14 @@ if __name__ == "__main__":
     my_config.reporters = []  # To prevent summary to stdout
     my_config.stdout_capture = False  # For test output
     my_config.stderr_capture = False  # For test output
-    (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
-    if not my_config.paths:  # No path provided, trying to load dit manually
-        if os.path.isfile(what_to_run):  # File is provided, load it
-            my_config.paths = [what_to_run]
-        else:  # Dir is provided, find subdirs ro run
-            my_config.paths = _get_dirs_to_run(base_dir)
+    (base_dir, what_to_run) = _bdd_utils.get_path_by_env(os.environ)
+    features = set()
+    for feature in what_to_run:
+        if os.path.isfile(feature) or glob.glob(os.path.join(feature, "*.feature")):  # File of folder with "features"  provided, load it
+            features.add(feature)
+        elif os.path.isdir(feature):
+            features |= set(_get_dirs_to_run(feature))  # Find "features" subfolder
+    my_config.paths = list(features)
     _BehaveRunner(my_config, base_dir).run()
 
 
index f0a4b5dbb873fe9d38565eb3d82f0b34adb3a8b0..6c4dbb7028a66e5701e1229e3d60aac0363a5d65 100644 (file)
@@ -4,6 +4,7 @@ BDD lettuce framework runner
 TODO: Support other params (like tags) as well.
 Supports only 1 param now: folder to search "features" for.
 """
+import os
 import _bdd_utils
 
 __author__ = 'Ilya.Kazakevich'
@@ -108,6 +109,8 @@ class _LettuceRunner(_bdd_utils.BddRunner):
 
 
 if __name__ == "__main__":
-    (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
-    _bdd_utils.fix_win_drive(what_to_run)
-    _LettuceRunner(base_dir, what_to_run).run()
\ No newline at end of file
+    (base_dir, what_to_run) = _bdd_utils.get_path_by_env(os.environ)
+    if len(what_to_run) > 1:
+        raise Exception("Lettuce can't run more than one file now")
+    _bdd_utils.fix_win_drive(what_to_run[0])
+    _LettuceRunner(base_dir, what_to_run[0]).run()
\ No newline at end of file