public void execute() throws MojoExecutionException {
    if (skip || skipTests) {
      getLog().info("Test execution is skipped");
    } else {

      final File[] testSourceDirectories = getSourceDirectories(SourceDirectory.TEST);
      final File[] allSourceDirectories =
          getSourceDirectories(SourceDirectory.TEST, SourceDirectory.COMPILE);

      if (testScript == null || "".equals(testScript)) {

        // Generate test script

        try {
          NamespaceInFile[] ns =
              new NamespaceDiscovery(getLog(), testOutputDirectory, testDeclaredNamespaceOnly)
                  .discoverNamespacesIn(testNamespaces, testSourceDirectories);

          File testFile = File.createTempFile("run-test", ".clj");
          final PrintWriter writer = new PrintWriter(new FileWriter(testFile));

          for (NamespaceInFile namespace : ns) {
            writer.println("(require '" + namespace.getName() + ")");
          }

          String testClj = generateTestScript(ns);

          writer.println(testClj);

          writer.close();

          testScript = testFile.getPath();

        } catch (IOException e) {
          throw new MojoExecutionException(e.getMessage(), e);
        }

        // throw new MojoExecutionException("testScript is empty or does not exist!");
      } else {
        File testFile = new File(testScript);

        if (!testFile.exists()) {
          testFile = new File(getWorkingDirectory(), testScript);
        }

        if (!(testFile.exists())) {
          throw new MojoExecutionException("testScript " + testFile.getPath() + " does not exist.");
        }
      }

      getLog().debug("Running clojure:test against " + testScript);

      callClojureWith(
          allSourceDirectories,
          outputDirectory,
          testClasspathElements,
          "clojure.main",
          new String[] {testScript});
    }
  }
  protected String generateTestScript(NamespaceInFile[] ns) throws IOException {
    StringWriter testCljWriter = new StringWriter();
    copy(ClojureRunTestMojo.class.getResourceAsStream("/default_test_script.clj"), testCljWriter);

    StringBuilder runTestLine = new StringBuilder();
    runTestLine.append("(run-tests");
    for (NamespaceInFile namespace : ns) {
      runTestLine.append(" '" + namespace.getName());
    }
    runTestLine.append(")");

    return testCljWriter.toString().replace("(run-tests)", runTestLine.toString());
  }
  /**
   * Discover namespaces in a list of source directories filtered by a list of namespace regexs
   *
   * @param namespaceFilterRegexs An array of regexs to use to filter files
   * @param paths The path to discover in
   * @return An array of {@link NamespaceInFile} instances.
   * @throws MojoExecutionException Something went wrong...
   */
  public NamespaceInFile[] discoverNamespacesIn(String[] namespaceFilterRegexs, File... paths)
      throws MojoExecutionException {

    if (namespaceFilterRegexs == null || namespaceFilterRegexs.length == 0) {
      namespaceFilterRegexs = new String[] {".*"};
    }

    Set<NamespaceInFile> namespaces = new HashSet<NamespaceInFile>();

    for (NamespaceInFile namespace : discoverNamespacesInPath(paths)) {

      boolean toAdd = !compileDeclaredNamespaceOnly;
      for (String regex : namespaceFilterRegexs) {

        if (regex.startsWith("!")) {
          // exclude regex
          if (Pattern.compile("^" + regex.substring(1)).matcher(namespace.getName()).matches()) {
            toAdd = false;
            break;
          }

        } else {
          // include regex
          if (Pattern.compile("^" + regex).matcher(namespace.getName()).matches()) {
            toAdd = true;
          }
        }
      }

      if (toAdd) {
        namespaces.add(namespace);
      } else if (log.isDebugEnabled()) {
        log.debug("Filtered namespace " + namespace.getName() + " from clojure build.");
      }
    }
    return namespaces.toArray(new NamespaceInFile[] {});
  }