public RunTestsLocallyAction() {
    this.settings = TmcSettings.getDefault();
    this.courseDb = CourseDb.getInstance();
    this.projectMediator = ProjectMediator.getInstance();
    this.resultDisplayer = TestResultDisplayer.getInstance();
    this.dialogDisplayer = ConvenientDialogDisplayer.getDefault();
    this.submitAction = new SubmitExerciseAction();
    this.eventBus = TmcEventBus.getDefault();

    putValue("noIconInMenu", Boolean.TRUE);
  }
  private void startRunningMavenProjectTests(final TmcProjectInfo projectInfo) {
    final File projectDir = projectInfo.getProjectDirAsFile();
    String goal = MAVEN_TEST_RUN_GOAL;
    Map<String, String> props = new HashMap<String, String>();
    InputOutput inOut = getIoTab();

    List<String> jvmOpts = new ArrayList<String>();

    Integer memLimit = getMemoryLimit(projectInfo.getProject());
    if (memLimit != null) {
      jvmOpts.add("-Xmx" + memLimit + "m");
    }

    jvmOpts.add("-D" + ERROR_MSG_LOCALE_SETTING + "=" + settings.getErrorMsgLocale().toString());

    props.put("tmc.test.jvm_opts", StringUtils.join(jvmOpts, ' '));

    final ProcessRunner runner =
        new MavenRunBuilder()
            .setProjectDir(projectDir)
            .addGoal(goal)
            .setProperties(props)
            .setIO(inOut)
            .createProcessRunner();

    BgTask.start(
        "Running tests",
        runner,
        new BgTaskListener<ProcessResult>() {
          @Override
          public void bgTaskReady(ProcessResult processResult) {
            File resultsFile =
                new File(
                    projectDir.getPath()
                        + File.separator
                        + "target"
                        + File.separator
                        + "test_output.txt");
            log.log(
                Level.INFO,
                "Next calling handleTestResults: projectInfo: {0}, file: {1}",
                new Object[] {projectInfo.getProjectDirAbsPath(), resultsFile.exists()});
            handleTestResults(projectInfo, resultsFile);
          }

          @Override
          public void bgTaskCancelled() {}

          @Override
          public void bgTaskFailed(Throwable ex) {
            dialogDisplayer.displayError("Failed to run tests:\n" + ex.getMessage());
          }
        });
  }
  private void startRunningSimpleProjectTests(
      final TmcProjectInfo projectInfo, FileObject testDir, List<TestMethod> testMethods) {
    File tempFile;
    try {
      tempFile = File.createTempFile("tmc_test_results", ".txt");
    } catch (IOException ex) {
      dialogDisplayer.displayError("Failed to create temporary file for test results.", ex);
      return;
    }

    try {
      ArrayList<String> args = new ArrayList<String>();
      args.add("-Dtmc.test_class_dir=" + FileUtil.toFile(testDir).getAbsolutePath());
      args.add("-Dtmc.results_file=" + tempFile.getAbsolutePath());
      args.add("-D" + ERROR_MSG_LOCALE_SETTING + "=" + settings.getErrorMsgLocale().toString());

      if (endorsedLibsExist(projectInfo)) {
        args.add("-Djava.endorsed.dirs=" + endorsedLibsPath(projectInfo));
      }

      Integer memoryLimit = getMemoryLimit(projectInfo.getProject());
      if (memoryLimit != null) {
        args.add("-Xmx" + memoryLimit + "M");
      }

      args.add("fi.helsinki.cs.tmc.testrunner.Main");

      for (int i = 0; i < testMethods.size(); ++i) {
        args.add(testMethods.get(i).toString());
      }
      InputOutput inOut = getIoTab();

      final File tempFileAsFinal = tempFile;
      ClassPath classPath = getTestClassPath(projectInfo, testDir);
      runJavaProcessInProject(
          projectInfo,
          classPath,
          "Running tests",
          args,
          inOut,
          new BgTaskListener<ProcessResult>() {
            @Override
            public void bgTaskReady(ProcessResult result) {
              log.info("Test run standard output:");
              log.info(result.output);
              log.info("Test run error output:");
              log.info(result.errorOutput);

              if (result.statusCode != 0) {
                log.log(Level.INFO, "Failed to run tests. Status code: {0}", result.statusCode);
                dialogDisplayer.displayError("Failed to run tests.\n" + result.errorOutput);
                tempFileAsFinal.delete();
                return;
              }

              try {
                handleTestResults(projectInfo, tempFileAsFinal);
              } finally {
                tempFileAsFinal.delete();
              }
            }

            @Override
            public void bgTaskCancelled() {
              tempFileAsFinal.delete();
            }

            @Override
            public void bgTaskFailed(Throwable ex) {
              tempFileAsFinal.delete();
              dialogDisplayer.displayError("Failed to run tests", ex);
            }
          });

    } catch (Exception ex) {
      tempFile.delete();
      dialogDisplayer.displayError("Failed to run tests", ex);
    }
  }