利用RCT实现与Linux服务器的文件互传

前言

情人节的晚上,情侣们有的去吃饭、有的去看电影。虽然小A的女朋友也买了电影票,但是苦逼小A却要对应用的不同启动模式来做测试。。。
其实测试过程并不繁琐:应用启动的时候需要读取一个properties的配置文件,小A只需要更改配置文件中各配置项的值,然后调用启动脚本,验证应用启动正常就ok了。
配置文件conf.properties 的内容如下:

quickInit=true haMode=false wait=true notifyAll=false alwaysOnline=true 

可现在的问题是,文件里有5个配置项,每个配置项都有true和false两个值供配置。就是说,根据不同的组合,至少要验证32组参数。。。。额,小A看看距离下班的时间,再看看女朋友发来的短信,一身冷汗。

小A首先确认了测试步骤:
1. 登陆Linux,修改Linux的配置文件
2. 启动应用
3. 查看应用的java进程是否存在,如果不存在,说明启动失败,肯定有问题。(其实如果进程存在,还是可能有问题的,这里为了举例子忽略掉这种情况)
然后重复上述过程,不停地更改这5个配置项的true、false,32次,就测完了。

小A掐指一算,即使我耐心的测完32种情况,日后需要再做回归测试怎么办呢?
OK,小A决定借助RCT来实现眼前的问题。

要想实现对配置文件的修改,有两种方式
第一种:直利用shell命令,直接修改conf.properties 文件。
第二种:由于是properties文件,而java对于properties文件的修改那叫一个舒服,可以把properties文件先下载到本地,或者直接生成一个properties文件。然后利用java程序来修改properties文件,之后使用RCT把文件上传回原来的目录,就实现了对文件的修改。

小A果断选择了第二种方式,代码如下:

public class ServerConfTest {
    // RCT客户端     private SSHClient           client    = null;
    // 配置文件的名字     private static final String FILE_NAME = "conf.properties";

    @Before
    public void setUp() {
        client = new SSHClient("192.168.0.1", "username", "password");
    }

    @Test
    public void testConfValue() {
        // 组合5个配置项,生成32个配置文件         for (int quickInit = 0; quickInit < 2; quickInit++) {
            for (int haMode = 0; haMode < 2; haMode++) {
                for (int wait = 0; wait < 2; wait++) {
                    for (int notifyAll = 0; notifyAll < 2; notifyAll++) {
                        for (int alwaysOnline = 0; alwaysOnline < 2; alwaysOnline++) {
                            // 根据关键字先停止应用                             client.killProcess("appA");

                            // 在本地生成properties对象                             Properties p = new Properties();
                            p.put("quickInit", quickInit == 0 ? "true" : "false");
                            p.put("haMode", haMode == 0 ? "true" : "false");
                            p.put("wait", wait == 0 ? "true" : "false");
                            p.put("notifyAll", notifyAll == 0 ? "true" : "false");
                            p.put("alwaysOnline",alwaysOnline== 0 ? "true" : "false");

                            // 把properties对象保存成文件                             storePropertyFile(p);

                            // 上次文件至Linux服务器                             String res = client.uploadFile(FILE_NAME,
                                    "/home/username/appA/conf");
                            // 保证上传成功,没有返回错误信息                             Assert.assertEquals("", res);

                            // 调用启动的启动脚本                             client.excuteScript("/home/username/appA/conf/bin/start.sh");

                            // 根据关键字获取进程号,如果不为空,表示程序已经启动成功                             String pid = client.getProcessID("appA");
                            Assert.assertTrue("Can't find process id", StringUtils.isNotBlank(pid));
                        }
                    }
                }
            }
        }
    }

    /**
     * 把properties对象写入文件
     * 
     * @param p
     */     private void storePropertyFile(Properties p) {
        File file = new File(FILE_NAME);
        FileOutputStream output = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            output = new FileOutputStream(file);
            p.store(output, null);
            output.close();
        } catch (Exception e) {
            Assert.fail("Create properties failed!");
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    Assert.fail("Close output stream failed!");
                }
            }
        }
    }
}

运行一下,32种配置方式一一跑过,没有问题。小A看看表,还有5分钟下班,刚好有时间把这个case加入持续集成,以后就可以自动运行测试啦!

本节中,只介绍了上传文件的具体做法,其实下载的方式也是一样的,可以参考下面的API:

   /**
     * 将本地文件上传至远端服务器的指定位置
     * 
     * @param localFilePath 本地文件的全路径名
     * @param remoteTargetDirectory 远程服务器的目的路径
     * @return 结果信息
     */     public String uploadFile(String localFilePath, String remoteTargetDirectory);

    /**
     * 将服务器上的文件下载到本地,并保存
     * 
     * @param remoteTargetPath 远程服务器的目标文件全路径名
     * @param localPath 本地文件的全路径名
     * @return
     */     public void downloadFile(String remoteTargetPath, String localPath);

    /**
     * 将本地文件夹上传至远端服务器的指定位置
     * 
     * @param localDirectory 本地文件夹的全路径名
     * @param remoteTargetDirectory 远程服务器的目的路径
     * @return 结果信息
     */     public String uploadFolder(String localDirectory, String remoteTargetDirectory);

原理

Orion-ssh2支持使用SCPClient来实现文件的上传&下载。RCT对SCPClient做了封装,大大简化了用户的操作,仅一个API调用,即可实现。

在下一集里,小A又将经受怎样的磨难,他又将如何化解呢?
欢迎关注Java与Linux交互的利器——RCT系列文章(四)

如果有更好的意见或者建议,或者有使用中不爽的地方,或者是找到了bug,欢迎随时联系和骚扰。