草庐IT

Appium - 入门指南(偏重于实际操作)

关你屁事滚远点 2023-05-07 原文

前言

此文章 偏向于实操
appium支持在不同平台上(windows,linux、mac) - 使用测试脚本(支持不同语言C #,json,Ruby等等) - 模拟测试各个平台的app(web、windows、mobile等)运行情况,支持ios和安卓平台上的原生应用,web应用和混合运用
appium类库封装了标准Selenium客户端类库,为用户提供所有常见的JSON格式selenium命令以及额外的移动设备控制相关的命令,如多点触控手势和屏幕朝向。

一、 Appium介绍

官网:http://appium.io/docs/cn/about-appium/intro/

这里主要是windows平台下的安装和使用。

1.1 设计理念

1.1.1 使用系统自带的自动化框架

使用各个系统自带的自动化框架可以让appium 独立运行

  • 不需要把 Appium 特定的或者第三方的代码编译进应用
  • 不用为了自动化而重新编译或修改应用
  • 各个系统使用的自动化框架:
    iOS 9.3 及以上: 苹果的 XCUITest
    iOS 9.3 及以下: 苹果的 UIAutomation
    Android 4.3+: 谷歌的 UiAutomator / UiAutomator2
    Android 2.3+: 谷歌的 Instrumentation. (通过绑定独立的项目—— Selendroid 提供对 Instrumentation 的支持)
    Windows: 微软的 WinAppDriver

1.1.2 支持多种语言 --WebDriver API

把各种系统本身提供的框架包装进一套 API —— WebDriver API 中
WebDriver(也叫「Selenium WebDriver」)。
在WebDriverAPI中,规定了一个客户端-服务器协议(称为 JSON Wire Protocol),按照这种客户端-服务器架构,可以使用任何语言编写的客户端向服务器发送适当的 HTTP 请求。

Appium & WebDriver 客户端在技术上而言不是「测试框架」,而是「自动化程序库」

1.2 架构

1.2.1 客户端 / 服务器架构

Appium 的核心一个是暴露 REST API 的 WEB 服务器。它接受来自客户端的连接,监听命令并在移动设备上执行,答复 HTTP 响应来描述执行结果

1.2.2 Appium服务器

Appium 是一个用 Node.js 写的服务器。可以从源码构建安装或者从 NPM 直接安装:

$ npm install -g appium
$ appium
  1. 它监听符合API规范,从WebDriver 传入的HTTP request。
  2. WebDriver是一个W3C规范,Appium团队为该协议添加了一些扩展,使其适用于web浏览器,同时也适用在任何设备上测试的任何应用程序。
  3. Appium Server服务器需要在Node.js web服务器中运行。
    • Node.js web服务器可以在运行测试之前在本地机器上启动,也可以托管Appium服务器-让它作为运行测试的一部分。

1.2.3 Appium 客户端

Appium 客户端,不同客户端支持不同语言,来发起http命令。比如postman,Appium server gui等等

  1. 让Appium客户端与Appium Server服务器交互
  2. 解读WebDriver协议,将WebDriver协议转换为我们可以轻松使用的客户端库。
    Appium提供了相应客户端的库。比如C# 有NuGet包。

1.2.4 会话(Session)

自动化始终在一个会话的上下文中执行。
通过客户端程序库以各自的方式发起与服务器的会话,但最终都会发给服务器一个 POST /session 请求,请求中包含一个被称作「预期能力(Desired Capabilities)」的 JSON 对象。这时服务器就会开启这个自动化会话,并返回一个用于发送后续命令的会话 ID。

1.2.5 预期能力(Desired Capabilities)

预期能力(Desired Capabilities)是一些发送给 Appium 服务器的键值对集合(比如 map 或 hash),它告诉服务器我们想要启动什么类型的自动化会话。
也有许多能力(Capabilities)可以修改服务器在自动化过程中行为。例如,我们可以将 platformName 能力设置为 iOS,以告诉 Appium 我们想要 iOS 中的应用会话,而不是 Android 或者 Windows 应用会话

二、环境配置

  1. 安装 npm添加链接描述, https://nodejs.org/en/

  2. 安装Appium:Appium 有命令行版本和桌面版本。可以两个都装上,桌面版本:在appium官网下载并安装Appium。命令行版本,管理员模式运行cmd:npm install -g appium 可能需要设置网络代理。

  3. 安装 node.js, https://nodejs.org/en/download/

  4. 安装 UIRecorder ,https://github.com/Microsoft/WinAppDriver/releases

  5. 安装结束后,在cmd界面输入“appium-doctor”检查是否缺少东西。

  6. 电脑启用“开发者模式”

  7. 添加环境变量

  8. 安装各平台应用的驱动程序,通过驱动程序,Appium server才能将我们的测试命令翻译给Appium客户端以及应用

  • WinAppDriver - Windows平台的驱动程序。针对windows应用自动化 WinAppDriver
    • UiAutomator2 - Android,它是Android SDK 安装包的一部分,安装 Java and Android SDK后就可以运行了
    • XCUITest - Mac,ios 研发需要Xcode,Xcode只适用于Mac
  1. 安装Appium inspector。用来查看、定位界面元素。如果使用有问题,可以去github上搜索:https://github.com/appium/appium-desktop/issues
    Appium Inspector 有两种版本,
  • 桌面app,下载链接https://github.com/appium/appium-inspector/releases

    • Appium 1.22版本之前都附带了Inspector 工具,入口在打开之后的搜索图标里(如下图),新版的inspector已经和Appium server不在一起了,需要单独安装。
  • web应用,由Appium Pro托管。直接打开网页就可以 https://inspector.appiumpro.com/
    这两个应用程序有完全相同的功能,开网页版会更容易,并节省磁盘空间,同时可以保持多个标签打开!

需要注意的是Appium Inspector设计为默认使用Appium 2.0 (W3C WebDriver协议)。因此,如果是从Appium Desktop(默认情况下设计为使用Appium 1.x)迁移,可能会有一些不同的地方

appium-doctor提示问题以及解决办法:

2.1ANDROID_HOME is not set

解决办法

  • 安装过adb的可以在系统变量-path中找到adb的安装路径(因为我用自己安装的路径,缺少android.bat文件,所以我这里解决办法是采用adb路径是安装vs2022时顺带安装的-勾选移动应用开发,包含AndroidSDK项)
  • 电脑-高级系统设置-系统变量-新增变量ANDROID_HOME ,值设置为adb 文件夹的路径。
  • adb完整路径是C:\Microsoft\AndroidSDK\25\platform-tools,ANDROID_HOME路径设置为C:\Microsoft\AndroidSDK\25

2.2 JAVA_HOME is not set

解决办法:

  • 在系统变量中找到找到JDK的安装路径
  • 新建变量JAVA_HOME,JDK的路径。这里直接复制完整路径即可。

成功解决之后再次测试appium-doctor,提示全部ok

✔ ANDROID_HOME is set to "C:\Microsoft\AndroidSDK\25"
✔ JAVA_HOME is set to "C:\Program Files\Microsoft\jdk-11.0.12.7-hotspot\bin."
✔ ADB exists at C:\Microsoft\AndroidSDK\25\platform-tools\adb.exe
✔ Android exists at C:\Microsoft\AndroidSDK\25\tools\android.bat
✔ Emulator exists at C:\Microsoft\AndroidSDK\25\tools\emulator.exe
✔ Android Checks were successful.

✔ All Checks were successful
(node:25404) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)

三、Appium - 测试程序详细解析

一个简单的自动化程序主要分为启动、交互。
不管哪个客户端,启动的步骤和所需要的参数都是一样的。
启动前要设置初始化参数,告知服务器启动哪一个应用app,在哪个平台,用哪个版本
交互要确认交互的对象 - 哪一个ui元素,交互的动作,以及如何判断动作结束

3.1 Appium 服务器初始化参数(Capability)

AppiumOptions是Appium中一个关键类
在启动应用时可以设置这些类中的这些参数 http://appium.io/docs/cn/writing-running-appium/caps/#appium-capability

3.1.1 Windows应用设置参数

keyName描述Value
appiumOptions.App应用exe本地绝对路径_或_应用id
appiumOptions.PlatformName操作系统“windows”;
appiumOptions.DeviceName设备类型“windowsPC”;

上面这三个是Windows应用必须要设置的

3.1.2 Android应用设置参数

keyName描述Value
platformName使用的手机操作系统iOS, Android等
platformVersion手机操作系统的版本例如 7.1, 4.4
deviceName使用的手机或模拟器类型adb devices命令查看当前设备名称。在 Andorid 上虽然这个参数目前已被忽略,但仍然需要添加上该参数。 为确保在连接多个设备时连接到正确的 Android 设备,请使用 udid 功能。
appActivity指从你的包中所要启动的 Android acticity。他通常需要在前面添加. (例如 使用 .MainActivity 代替 MainActivity)MainActivity, .Settings
appPackage运行的 Android 应用的包名com.example.android.myApp, com.android.settings
app本地绝对路径_或_远程 http URL 所指向的一个安装包(.ipa,.apk,或 .zip 文件)。Appium 将其安装到合适的设备上。请注意,如果您指定了 appPackage 和 appActivity 参数(见下文),Android 则不需要此参数了。该参数也与 browserName 不兼容。/abs/path/to/my.apk 或 http://myapp.com/app.ipa

3.2 UI元素定位与交互

如果是WPF程序,在该控件的Automation里面可以找到对应的设置,比如Name,AccessibilityID。
在inspector 里面,可以看到界面元素具体的值
http://appium.io/docs/en/commands/element/find-elements/index.html#selector-strategies

method描述Value
IDNative element identifier. resource-id for android; name for iOS.
AccessibilityIDAutomationID
Name组件的名称
class Nameui组件的类型BUTTON,MENUBAR等等
xpath路径定位,依赖元素绝对路径或相关属性定位。不太推荐这种方式

四、Appium实战 之启动应用

4.1 通过Inspector启动 - 记事本应用

Appium inspector是一个软件,通过他可以查看界面上的所有元素信息,比如某个按键的名字、控件类型、xy坐标,等等
通过简单设置Appium inspector中的参数,快速启动应用,一方面为后面定位控件元素做好准备,一方面可以通过启动应用所需要的参数,参考到自动化程序中。

  1. 管理员模式启动Appium server
    可以管理员启动桌面版Appium Server GUI.exe,输入Host127.0.0.1和端口4723。
    也可以通过管理员模式启动cmd,输入appium,启动命令行版本
    因为inspector(或者其他客户端)与 应用(或者模拟器)之间的通讯交互都需要通过Appium server来传达与翻译。所以要先启动Appium server。
    后续交互历史记录在Appium server界面也可以看到详细信息。

  2. 管理员模式启动Appium Inspector,设置Remote path
    如果Appium版本是1.x 而inspector 版本是新的,就需要设置远端路径 - Remote path 为/wd/hub
    如果Appium 版本是2.x 则不用设置
    Appium版本为 v1.22.3,所以需要设置

  • wd 可以理解是WebDriver 的缩写
  • hub 是指主(中心) 节点,在selenium 分布式里中心节点
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/edec3033d4b54cfe8313ae5481ceafe2.png
  1. 添加Capabilities
    在Desired Capabilities 下面,依次添加需要启动应用的信息。

    app:要启动的应用,这里添加notepad.exe的路径
    deviceName:启动的设备
    platformName:这个应用所需要使用的平台
    这三个信息是必要的。告诉Appium inspector我们需要在何种环境下启动何种应用
    右边会自动将我们填入的信息转换成JSON 表达方式
    点击save,保存现在的信息。
  2. 点击Start Session

    启动session后,inspector会启动记事本应用,
  • 左侧界面预览区,是和当前应用同步界面的预览画面,不会实时更新。需要手动点击刷新按钮来同步画面。但是在预览区点击按钮,实际打开的应用会实时同步操作。
  • App Source,查看当前界面元素信息,这些信息可以用来帮助我们在写自动化时定位某个界面元素。

五、Appium实战 之编写Mstest 自动化程序

自动化测试程序是模拟应用启动、运行,以及其他的一些特定操作。
所以基于inpector启动应用的流程,我们可以在自己加一些操作,比如输入字符串,保存文档等。
我这里是对自己写的WPF应用进行自动化测试,先在文本框中输入字符串,然后保存文档。

5.1 新建MSTest 测试项目,或者单元测试项目

5.2 添加NuGet包

项目上右键 - NuGet包管理 - 搜索并添加NuGet包,需要添加以下三个:
- Microsoft.WinAppDriver.Appium.WebDriver
- Selenium.WebDriver
- Selenium.Support

在安装时,注意看下面的依赖项 版本说明,比如.Appium.WebDriver,需要Selenium 包相关版本为3.8.0+。工具-程序包管理控制台, 输入Get-Package 获取当前项目的NuGet包信息
我安装的版本信息如下,

  • Appium.WebDriver {5.0.0-alpha} NodepadTest
  • Selenium.WebDriver {4.0.0} NodepadTest - Selenium.Support {4.0.0} NodepadTest

官网Samples项目版本如下 (Appium官方样例代码下载地址:https://github.com/Microsoft/WinAppDriver/tree/v1.0#using-appium

  • Microsoft.WinAppDriver.Appium.We… {1.0.1-Preview} NotepadCalculatorTest
  • Selenium.Support {3.8.0} NotepadCalculatorTest
  • Selenium.WebDriver {3.8.0} NotepadCalculatorTest

Appium版本更新的时候,会优化很多功能,如果报一些错误,可以试试把版本改一改。

  • Microsoft.WinAppDriver.Appium.WebDriver 这是一个用于Appium,临时的Selenium WebDriver的扩展,它实现了Windows应用程序驱动程序(WinAppDriver)的操作API功能。这仅用于预览目的。 Microsoft WinAppDriver 提供
  • Appium.WebDriver - Selenium Webdriver extension for Appium. 由Appium提供
https://www.nuget.org/packages 可以搜索关于NuGet包的相关信息

这两个包选择一个使用,我这里选择的- Appium.WebDriver {5.0.0-alpha} NodepadTest

5.3 添加session

  1. 添加using 引用库
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Service;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium;
using System;
using System.Threading;
using OpenQA.Selenium.Appium.Interactions;
using OpenQA.Selenium.Interactions;
using System.Collections.Generic;
using OpenQA.Selenium.Support.UI;
  1. 添加session 启动function,在method下调用这个函数的话,就可以启动该Application了。我这里用的是我自己写的一个WPF应用。可以用notepad.exe
public  WindowsDriver<WindowsElement> StartNodepadApplication()
        {
            //1.add capabilities
            var appiumOptions = new AppiumOptions();
            //appiumOptions.App = @"C:\Windows\System32\notepad.exe";//notepad
            appiumOptions.App = "D:\\test\\Appium\\WPFApplication\\AppiumMyApp\\AppiumMyApp\\bin\\x64\\Release\\net6.0-windows\\AppiumMyApp.exe";   
            appiumOptions.PlatformName = "windows";
            appiumOptions.DeviceName = "windowsPC";
            
            //2.start the driver
            var appiumLocalServer=new AppiumServiceBuilder().UsingAnyFreePort().Build();
            appiumLocalServer.Start();
            var driver = new WindowsDriver<WindowsElement>(appiumLocalServer, appiumOptions);
           //return the sever session
            return driver;
     }
  1. 完善TestMethod,定位界面元素,并进行交互操作
    • 点击clear button
    • 点击编辑button
    • 发送字符串到文本框
    • 点击save button
    • 建立DefaultWait,每500ms轮询一次,查看是否弹出了保存文件的对话框,我这里用来界面出现保存button ,如果出现表示前面的步骤执行结束。才会继续执行后续的动作
    • 同样建立第二个DefaultWait,等到界面弹出一个对话框 ,包含一个元素Name为“文件已导出”,表示文件已经保存完毕了。
[TestMethod]
        public void TestWaitForProgressBar()
        {
       	 //start session
            var session = StartNodepadApplication();
        // FindUIElementMethod1 -Name,click clear button
            var clearButton = session.FindElementByName("Clear");
            clearButton.Click();
       // FindUIElementMethod2 -AccessibilityId, click button
            var textBox = session.FindElementByAccessibilityId("MyTextBoxID");
            textBox.Clear();
       //SendKeys     
            textBox.SendKeys("-----------------------------------------\n");
            textBox.SendKeys("******************************************\n");
            textBox.SendKeys("my name is jerry\n");
            //click save
            var saveButton= session.FindElementByName("Save");
            saveButton.Click();
            
      //Wait for the progress to process for a while.untill Element appear or disappear
      //1.add a DefaultWait,Poll once every 500ms
            var wait = new DefaultWait<WindowsDriver<WindowsElement>>(session)
            {
                Timeout = TimeSpan.FromSeconds(60),
                PollingInterval = TimeSpan.FromMilliseconds(500)
            };
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

            //界面能找到,说明前面动作已经执行完毕
            wait.Until(d => d.FindElementByName("保存(S)"));
            //click save button in SaveFileDialog
            var dialogSavebutton = session.FindElementByName("保存(S)");
            dialogSavebutton.Click();

   	//2.
            var wait2 = new DefaultWait<WindowsDriver<WindowsElement>>(session)
            {
                Timeout = TimeSpan.FromSeconds(60),
                PollingInterval = TimeSpan.FromMilliseconds(500)
            };
            wait.IgnoreExceptionTypes(typeof(NoSuchElementException));

            //find element to verify save done
            wait.Until(d =>
            {
                return d.FindElementByName("文件已导出");
            });
            session.FindElementByName("确定").Click();

            textBox = session.FindElementByAccessibilityId("MyTextBoxID");
            textBox.Clear();
            textBox.SendKeys("file save done this is second time I am here-\n");

            session.Close();
        }

项目右键-运行测试-可以看到会开始执行自动化测试。

六、编写android自动化应用测试程序

6.1 inspector 连接真机

6.1.1获取连接真机app的相关参数

准备工作:手机开启开发者模式,(一般连续点击系统版本5下),开启usb 调试模式
最好是能使用root 命令的手机,因为我在使用普通手机时,出现了连接不上的问题
第三章提到过,安卓应用启动需要设置以下Capabilities,获取方式标注在了右边
可参考链接:https://blog.csdn.net/u012028250/article/details/120371345

keyName描述adb 命令
platformName手机操作系统Android
platformVersion操作系统版本adb shell getprop ro.build.version.release
deviceName手机或模拟器类型adb devices
appPackage运行的 Android 应用的包名手机上打开要测试的app,输入 adb shell "dumpsys window | grep mCurrentFocus"
appActivity从包中所要启动的 Android acticity同上

appPackage获取方式有如下几种:package都是com.xxx

  • adb shell pm list packages列出手机上所有的包,找到所需要的包名
  • adb shell am monitor 获取当前应用程序包名

appActivity获取方式:

  • adb shell dumpsys activity | findstr “mResume”
    com.sec.android.app.camera/.Camera t243} ---即appPackage / appActivity
  • adb shell "dumpsys window \| grep mCurrentFocus"

    mCurrentFocus=Window{c22cf8f u0 com.sec.android.app.camera/com.sec.android.app.camera.Camera} ---即appPackage / appActivity
    获取之后填入到inspector中

图片中SM-A336B是通过adb shell getprop ro.product.model获取的,指的是手机型号,可填可不填。
appium:automationName:指以什么方式解析界面元素UiAutomator2
填完之后,点击start session,手机会自动安装appium 相关软件,然后就可以启动手机中应用,并且获取界面控件元素了。

6.1.1查看界面元素信息

6.2 MSTest测试程序连接真机

6.2.1 参考inspector启动应用


        private AndroidDriver<AndroidElement> StartApp()
        {
            System.Environment.SetEnvironmentVariable("ANDROID_HOME", @"C:\\Microsoft\\AndroidSDK\\25");
            System.Environment.SetEnvironmentVariable("JAVA_HOME", @"C:\\Program Files\\Microsoft\\jdk-11.0.12.7-hotspot");

            //connect to a device or emulator
            var capabilities = new AppiumOptions();
             capabilities.DeviceName=@"SM-A336B-58f407b9db347ece";
            //capabilities.DeviceName = @"58f407b9db347ece";
            capabilities.AutomationName = @"UiAutomator2";
            capabilities.PlatformName = "Android";
            capabilities.PlatformVersion = "12";

            //specifying which app we want to install or launch
            capabilities.AddAdditionalAppiumOption("appPackage", "com.sec.android.app.camera");
            capabilities.AddAdditionalAppiumOption("appActivity", "com.sec.android.app.camera.Camera");
            
            //specify startup flags appium sever to execute adb shell commands
            var serveroptions = new OptionCollector();
            var relaxedSecurityOption = new KeyValuePair<string, string>("--relaxed-security", "");
            serveroptions.AddArguments(relaxedSecurityOption);
            var _appiumLocalService = new AppiumServiceBuilder().UsingAnyFreePort().WithArguments(serveroptions).Build();
            
            //start the service
            _appiumLocalService.Start();
            var driver = new AndroidDriver<AndroidElement>(_appiumLocalService, capabilities);
            return driver;
        }

6.2.1 完善TestMethod


[ClassCleanup]//clear up local service
static public void CleanUp()
{
    _appiumLocalService?.Dispose();
    _appiumLocalService = null;
}
       
[TestMethod]
public void TestListInstallPackage()
{
    AndroidDriver<AndroidElement> driver = StartApp();
    //use shell command to list all installed package on the device
    string script = "mobile:shell";
    var arguments = new Dictionary<string, string>
    {
        {"command","pm list package" },
        { "----show-versioncode",""},
    };
    var list = driver.ExecuteScript(script, arguments);
    Assert.IsNotNull(list);
    Console.Write(list);
}

然后点击运行测试,就可以看到手机相机启动了。

有关Appium - 入门指南(偏重于实际操作)的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  4. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  5. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  6. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  7. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  8. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  9. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  10. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

随机推荐