【问题标题】:Start appium automatically within test execution?在测试执行中自动启动appium?
【发布时间】:2014-03-23 06:45:18
【问题描述】:

有没有办法让 appium 在我为 junit 测试编写的代码中启动?因为 appium 只需要在我的测试运行时运行,所以让 appium 服务器始终运行对我来说没有意义。

现在我正在使用 junit 和 maven 来运行测试构建。由于 appium 的稳定性问题,它有时会在构建过程中死掉,从而导致所有剩余测试失败。我想知道是否可以在 @Before 方法中添加一些东西来启动 appium 服务器,然后再将 WebDriver 连接到它,然后在 @After 方法中终止它。这应该可以解决 appium 失败的任何问题,因为它可以在开始下一次测试之前重置。

仍在研究 java 中一般的启动和结束进程,看看这是否可行。如果我解决了这个问题,我会更新这篇文章以帮助其他有兴趣以这种方式进行测试的人。

【问题讨论】:

    标签: java appium


    【解决方案1】:

    弄清楚如何通过在代码中运行终端命令来使其工作

    @Before
    public void setUp() throws Exception {
        closeSimulatorAndInstruments(); // also closes any appium servers
        appium = Runtime.getRuntime().exec("/usr/local/bin/appium");
        Thread.sleep(1000); // wait for appium to start up, not sure how to check the status
        ... // start test
    }
    
    @After
    public void tearDown() throws Exception {
        captureScreenshot(testName.getMethodName());
        driver.quit();
        appium.destroy(); // kills the appium server so it wont collide with the next run
    }
    

    我看到运行 jenkins 的 CI 盒出现问题,但它可能不相关。在本地,这很好用,因为我不必再记得单独运行 appium 或检查它是否死了。但是,如果您需要查看可能包含重要错误的 appium 输出,则不建议这样做

    【讨论】:

      【解决方案2】:

      我为此编写了一个库。

      /**
       *@author Raghu Nair
       */
      public class Appium {
      
      private static volatile Appium instance;
      
      public static Appium getInstance(String outFile, String errFile) {
          if (instance == null) {
              synchronized (Appium.class) {
                  if (instance == null) {
                      instance = new Appium(outFile, errFile);
                  }
              }
          }
          return instance;
      }
      Process process;
      final String outFile;
      final String errFile;
      
      private Appium(String outFile, String errFile) {
          this.outFile = outFile;
          this.errFile = errFile;
      }
      
      public void start() throws IOException {
          if (process != null) {
              stop();
          }
      
          String processName = System.getProperty("appium.bin");
          String processString = processName + " -lt 180000";
          ProcessBuilder builder = new ProcessBuilder("bash");
          process = builder.start();
          OutputStream outStream = System.out;
          if (outFile != null) {
              outStream = new FileOutputStream(outFile);
          }
          OutputStream errStream = System.err;
          if (errFile != null) {
              errStream = new FileOutputStream(errFile);
          }
      
          handleStream(process.getInputStream(), new PrintWriter(outStream));
          handleStream(process.getErrorStream(), new PrintWriter(errStream));
          try (PrintWriter writer = new PrintWriter(process.getOutputStream())) {
              //writer.println("kill -9 `ps -ef | grep appium | cut -d' ' -f2`");
              writer.println("export PATH=$PATH:/usr/bin/:/usr/local/bin/");
              writer.println(processString);
              writer.flush();
          }
      
      }
      
      private void handleStream(final InputStream processOut, final PrintWriter writer) {
          Thread outHandler;
          outHandler = new Thread(new Runnable() {
              @Override
              public void run() {
                  try {
                      BufferedReader stdout = new BufferedReader(
                              new InputStreamReader(processOut));
                      String line;
                      while ((line = stdout.readLine()) != null) {
                          writer.println(line);
                          writer.flush();
                      }
                  } catch (IOException ex) {
                      ex.printStackTrace(System.err);
                  }
              }
          });
          outHandler.start();
      }
      
      public void stop() {
          System.out.println("Stopping the process");
          if (process != null) {
              try {
                  process.destroy();
                  process.getErrorStream().close();
                  process.getInputStream().close();
                  process.getOutputStream().close();
              } catch (IOException ex) {
                  ex.printStackTrace(System.err);
              }
          }
      }
      
      public static void main(String[] args) throws Exception {
          System.setProperty("appium.bin", "/Applications/Appium.app//Contents/Resources/node_modules/.bin/appium");
          Appium appium = Appium.getInstance("/Users/<user>/tmp/appium.out", "/Users/<user>/tmp/appium.err");
          appium.start();
          TimeUnit.SECONDS.sleep(30);
          appium.stop();
      }
      

      【讨论】:

        【解决方案3】:

        我以非常相似的方式解决了这个问题,使用DefaultExecutor 来跟踪 Appium 进程,以便在测试结束时将其销毁。这也允许在测试期间使用 DefaultExecuteResultHandler 注销 Appium 输出。

        为避免使用睡眠等待 Appium 启动,您可以在 try-catch 中创建 WebDriver 实例

        for (int i = 10; i > 0; i--) {
                try {
                    driver = new RemoteWebDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
                    // If we successfully attach to appium, exit the loop.
                    i = 0;
                } catch (UnreachableBrowserException e) {
                    LOGGER.info("Waiting for Appium to start");
                }
            }
        

        如果您想减少轮询频率,可以在 catch 块中添加睡眠。

        【讨论】:

          【解决方案4】:

          我看到我们可以改进上述解决方案。

          1. 为每个环境创建配置文件(定义 appium 主页)
          2. 您可以将进程输出流重定向到一个文件。文件名可以在配置文件中定义在 java 文件中。

          【讨论】:

            猜你喜欢
            • 2014-02-11
            • 1970-01-01
            • 2013-09-10
            • 2020-03-07
            • 2020-06-30
            • 2015-05-08
            • 2014-08-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多