在RCP程序中进行单元测试

  • Post author:
  • Post category:其他



最近刚刚接触RCP这个东西,其中如何进行单元测试让我头疼了好几天。

搜索了一下,倒是发现了许多测试工具,但是,要么是收钱的,要么是安装不方便,要么是

使用麻烦。


总之,没找到好用的。


最后,无奈之下,决定使用最古老的方式—–MOCK!这绝对不是一个好的方式,但是,如果你想


自如的进行单元测试,倒是一个可以考虑的方式。


RCP程序不同于WEB程序,RCP的程序就是普通的JAVA类,运行的时候也不需要额外的服务器。


那么,我们能不能象运行一个普通的JAVA类那样来运行一个RCP程序呢?

答案是否定的,因为RCP运行的时候需要RCP的环境。


那么我们就来MOCK!


例如我有一个 Editor 类,


java 代码

  1. public


    class

    NewOrderEditor

    extends

    EditorPart {

  2. private

    Text text_1;

  3. public


    void

    createPartControl(Composite parent) {
  4. …..
  5. …..
  6. }
  7. }

首先,我把这个类拷贝到测试目录里,然后改个名字,例如叫 NewOrderEditorMock.java。

然后,开始Mock,原则就是脱离一切 swt 等组件!

所有的 Text, Button, Table, TableItem, CheckBoxTableViewer 全部都自己写一个模拟类,

其中所需要的方法也实现一个模拟的。

例如这就是一个模拟类:

java 代码

  1. public


    class

    CheckboxTableViewer {

  2. private

    Table table =

    new

    Table();

  3. public


    static

    CheckboxTableViewer newCheckList(Composite parent,

    int

    style) {

  4. return


    new

    CheckboxTableViewer();
  5. }

  6. public

    Table getTable() {

  7. return

    table;
  8. }

  9. public

    Object[] getCheckedElements() {

  10. // TODO Auto-generated method stub
  11. java.util.List<TableItem> itemList = table.getTableItemList();
  12. java.util.List elementList =

    new

    ArrayList();

  13. for

    (TableItem item : itemList ) {

  14. if

    (item.isCheck()) {
  15. elementList.add(item.getData());
  16. }
  17. }

  18. if

    (elementList.size()==

    0

    ) {

  19. return


    null

    ;
  20. }

  21. return

    elementList.toArray(

    new

    Object[elementList.size()]);
  22. }

  23. public


    void

    selectLine(

    int

    line) {
  24. TableItem tableItem = table.getTableItemList().get(line);
  25. tableItem.setCheck(

    true

    );
  26. }
  27. }

java 代码

  1. public


    class

    Table {
  2. List<TableColumn> tableColumnList =

    new

    ArrayList<TableColumn>();
  3. List<TableItem> tableItemList =

    new

    ArrayList<TableItem>();

  4. public


    void

    setLinesVisible(

    boolean

    b) {
  5. }

  6. public


    void

    setHeaderVisible(

    boolean

    b) {
  7. }

  8. public


    void

    setBackground(Color color) {

  9. // TODO Auto-generated method stub
  10. }

  11. public


    void

    setLayoutData(GridData gd_tle_resultset) {

  12. // TODO Auto-generated method stub
  13. }

  14. public


    void

    removeAll() {

  15. // TODO Auto-generated method stub
  16. tableColumnList.clear();
  17. tableItemList.clear();
  18. }

  19. public

    TableItem getItem(

    int

    selectIndex) {

  20. // TODO Auto-generated method stub

  21. return

    tableItemList.get(selectIndex);
  22. }

  23. public


    void

    remove(

    int

    [] index) {

  24. // TODO Auto-generated method stub

  25. for

    (

    int

    i =

    0

    ; i< tableItemList.size(); i++) {

  26. for

    (

    int

    j =

    0

    ; j < index.length; j++) {

  27. if

    (i==index[j]) {
  28. tableItemList.remove(i);
  29. i–;

  30. break

    ;
  31. }
  32. }
  33. }
  34. }

  35. public


    int

    getItemCount() {

  36. // TODO Auto-generated method stub

  37. return

    tableItemList.size();
  38. }

  39. public

    TableItem[] getItems() {

  40. // TODO Auto-generated method stub

  41. return

    tableItemList.toArray(

    new

    TableItem[tableItemList.size()]);
  42. }

  43. public


    int

    getColumnCount() {

  44. // TODO Auto-generated method stub

  45. return

    tableColumnList.size();
  46. }

  47. public

    TableColumn getColumn(

    int

    n) {

  48. // TODO Auto-generated method stub

  49. return

    tableColumnList.get(n);
  50. }

  51. public

    List<TableColumn> getTableColumnList() {

  52. return

    tableColumnList;
  53. }

  54. public


    void

    setTableColumnList(List<TableColumn> tableColumnList) {

  55. this

    .tableColumnList = tableColumnList;
  56. }

  57. public

    List<TableItem> getTableItemList() {

  58. return

    tableItemList;
  59. }

  60. public


    void

    setTableItemList(List<TableItem> tableItemList) {

  61. this

    .tableItemList = tableItemList;
  62. }
  63. }

这么做确实很麻烦,不过好在很多方法都很容易模拟 —– 这不是你的水平高,而是因为那些

组件使用了MVC模式,写模拟方法的时候,根本无须考虑视图的问题。

至于鼠标点击按钮,就更容易了—–因为那好比直接调用类里的一个方法!

编写模拟的过程并不容易,因为有的时候,你会发现你要模拟更多的类—-在这个过程中,我

怀疑我做的到底有没有意义?不过我还是做了,因为只有做过了,才能知道。

终于,模拟类都写完了,我开始测试一个 editor 界面。

测试类真的是太好写了,我可以和程序中的任何一个类进行交互,因为目前这个模拟的界面

就是一个普通的类。

这其中我测试出了一些BUG,进行了修改。也测试出了一些模拟类的问题,当然也对其进行了

修改。

当全部的测试通过以后,我再使用eclipse的比较功能,把模拟的界面类和真正的界面类进行了

代码合并。

之后 …. …..

我还有下一个界面要进行编码,在编码之前,我重复之前的步骤,复制了一个模拟类,把 swt

等相关的东西删除了,导入模拟的类。这次我没那么麻烦,因为很多东西在上一个过程里都创建

好了。

直到这里,我仍然不知道我所做的是否有意义,因为这么做很麻烦—我每次都需要合并模拟类

和真正的类的代码。Eclipse的代码比较功能非常强大,但手动合并还是麻烦。

但是,所得到的回报就是测试非常方便,非常方便!

在我没有发现一个非常棒的工具之前,我还是暂时使用这种方式,直到项目的结束。

或许在结束之前,我就会因为模拟类的繁多而停止使用这种方式,

也或许直到结束,我都会一直使用这种方式,而且发现它会越来越好用。