需求描述
目前进程扩展项目代码写好之后,无法很好的进行调试,只能放到环境直接进行功能测试。
最好能有一种方式在功能测试之前,可以让开发人员提前调试自己的代码。
实现思路
目前项目中主要有如下方式可以调试代码。
- 单元测试。新建单元测试用例,构造入参,调试主方法。
- 远程调试。开启Agile的远程debug选项,进行业务操作时会进入到本地的断点中。
实现细节
单元测试
这种方式适合很多业务场景。但前提是必须要准确的构造入参。否则不一定能准确的重现正式环境的问题。
入参构造
一般常见的入参有:IAgileSession,INode,IEventInfo,可以写一个单元测试专用的类IAgileTestUtils,参考代码如下:
package com.purvar.agile.utils;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import com.agile.api.APIException;
import com.agile.api.AgileSessionFactory;
import com.agile.api.IAgileSession;
import com.agile.api.IDataObject;
import com.agile.api.ISignoffReviewer;
import com.agile.api.IStatus;
import com.agile.api.IWorkflow;
import com.agile.px.IEventDirtyCell;
import com.agile.px.IEventInfo;
import com.agile.px.IRoutableObjectEventInfo;
import com.agile.px.ISaveAsEventInfo;
import com.agile.px.ISignOffEventInfo;
import com.agile.px.IUpdateEventInfo;
import com.agile.px.IWFChangeStatusEventInfo;
/**
* 本类仅供单元测试使用,请勿在正式的功能代码中使用本类的任何方法.会报异常的<br>
* @deprecated 本类的所有方法仅供单元测试使用,请勿在正式功能中使用
* @author namelessmyth
* @see [相关类/方法]
* @since [2016年11月24日]
* @version 1.0 2016年11月24日
*/
public class IAgileTestUtils {
/**
* 构造AgileSession,仅供单元测试使用
* @author namelessmyth
* @since [2016年11月24日]
*/
public static IAgileSession getSession(String type) {
IAgileSession session = null;
String username = "admin";
String pwd = "tartan";
String url = null;
if ("dev".equals(type)) {
url = "http://192.168.2.134:7001/Agile";
} else if ("test".equals(type)) {
url = "http://10.8.0.25:7001/Agile";
} else if ("prod".equals(type)) {
url = "http://10.8.0.20:7001/Agile";
} else {
throw new RuntimeException("请指定正确的PLM环境类型,'prod'代表正式环境,请谨慎使用");
}
HashMap<Integer, String> params = new HashMap<Integer, String>();
params.put(AgileSessionFactory.USERNAME, username);
params.put(AgileSessionFactory.PASSWORD, pwd);
params.put(AgileSessionFactory.URL, url);
try {
session = AgileSessionFactory.createSessionEx(params);
} catch (APIException e) {
throw new RuntimeException("连接PLM错误", e);
}
return session;
}
/**
* 创建一个测试用的批准事件<br>
*
* @param data 事件中的数据对象
* @return IEventInfo
* @author namelessmyth
* @since [2016年7月20日]
*/
public static IEventInfo createISignOffEventInfo(final IDataObject data) {
IEventInfo event = new ISignOffEventInfo() {
public void setUserDefinedMap(Map arg0) throws APIException {
}
public Map getUserDefinedMap() throws APIException {
return null;
}
public int getEventType() throws APIException {
return 0;
}
public int getEventTriggerType() throws APIException {
return 1;
}
public String getEventSubscriberName() throws APIException {
return "事件订户名称";
}
public String getEventName() throws APIException {
return "测试专用事件名称";
}
public String getEventHandlerName() throws APIException {
return "事件处理器";
}
public IDataObject getDataObject() throws APIException {
return data;
}
public IWorkflow getWorkFlow() throws APIException {
return null;
}
public void setNotifyReviewers(boolean arg0) throws APIException {
}
public void setNotifyReviewerOption(int arg0) throws APIException {
}
public void setNotifyOriginator(boolean arg0) throws APIException {
}
public void setNotifyChangeAnalyst(boolean arg0) throws APIException {
}
public void setNotifiers(Collection arg0) throws APIException {
}
public void setComments(String arg0) throws APIException {
}
public boolean isNotifyReviewers() throws APIException {
return false;
}
public boolean isNotifyOriginator() throws APIException {
// TODO Auto-generated method stub
return false;
}
public boolean isNotifyChangeAnalyst() throws APIException {
return false;
}
public int getNotifyReviewerOption() throws APIException {
return 0;
}
public IDataObject[] getNotifiers() throws APIException {
return null;
}
public String getComments() throws APIException {
return null;
}
public void setUrgent(boolean arg0) throws APIException {
}
public void setTransferUsers(Collection arg0) throws APIException {
}
public void setSignoffForSelf(boolean arg0) throws APIException {
}
public void setSignoffForGroups(Collection arg0) throws APIException {
}
public void setEscalationUsers(Collection arg0) throws APIException {
}
public boolean isUrgent() throws APIException {
return false;
}
public boolean isSignoffForSelf() throws APIException {
return false;
}
public IDataObject[] getTransferUsers() throws APIException {
return null;
}
public IStatus getStatus() throws APIException {
return null;
}
public ISignoffReviewer[] getSignoffForGroups() throws APIException {
return null;
}
public IDataObject[] getEscalationUsers() throws APIException {
return null;
}
};
return event;
}
public static IEventInfo createIUpdateEventInfo(final IDataObject data) {
IEventInfo event = new IUpdateEventInfo() {
public IDataObject getDataObject() throws APIException {
return data;
}
public String getEventHandlerName() throws APIException {
return null;
}
public String getEventName() throws APIException {
return null;
}
public String getEventSubscriberName() throws APIException {
// TODO Auto-generated method stub
return null;
}
public int getEventTriggerType() throws APIException {
return 0;
}
public int getEventType() throws APIException {
return 0;
}
public Map getUserDefinedMap() throws APIException {
return null;
}
public void setUserDefinedMap(Map arg0) throws APIException {
}
public Integer[] getAttributeIds() throws APIException {
return new Integer[] { 1003 };
}
public IEventDirtyCell getCell(Object arg0) throws APIException {
return null;
}
public IEventDirtyCell[] getCells() throws APIException {
return null;
}
public Object getValue(Object arg0) throws APIException {
return null;
}
public void removeCell(Object arg0) throws APIException {
}
public IEventDirtyCell setCell(Object arg0, Object arg1) throws APIException {
return null;
}
};
return event;
}
public static IEventInfo createISaveAsEventInfo(final String newNumber, final Integer newSubclassId) {
IEventInfo event = new ISaveAsEventInfo() {
public void setUserDefinedMap(Map arg0) throws APIException {
}
public Map getUserDefinedMap() throws APIException {
return null;
}
public int getEventType() throws APIException {
return 0;
}
public int getEventTriggerType() throws APIException {
return 0;
}
public String getEventSubscriberName() throws APIException {
return null;
}
public String getEventName() throws APIException {
return null;
}
public String getEventHandlerName() throws APIException {
return null;
}
public IDataObject getDataObject() throws APIException {
return null;
}
public IEventDirtyCell setCell(Object arg0, Object arg1) throws APIException {
return null;
}
public void removeCell(Object arg0) throws APIException {
}
public Object getValue(Object arg0) throws APIException {
return null;
}
public IEventDirtyCell[] getCells() throws APIException {
return null;
}
public IEventDirtyCell getCell(Object arg0) throws APIException {
return null;
}
public Integer[] getAttributeIds() throws APIException {
return new Integer[] { 1081 };
}
public void setNewSubclassId(Integer arg0) throws APIException {
}
public void setNewNumber(String arg0) throws APIException {
}
public Integer getNewSubclassId() throws APIException {
return newSubclassId;
}
public String getNewNumber() throws APIException {
return newNumber;
}
};
return event;
}
/**
* 创建一个测试用的抽象事件父类<br>
*
* @param data 事件中的数据对象
* @return IEventInfo
* @author namelessmyth
* @since [2016年7月20日]
*/
public static IRoutableObjectEventInfo createIRoutableObjectEventInfo(final IDataObject data) {
IRoutableObjectEventInfo event = new IRoutableObjectEventInfo() {
public void setUserDefinedMap(Map arg0) throws APIException {
}
public Map getUserDefinedMap() throws APIException {
return null;
}
public int getEventType() throws APIException {
return 0;
}
public int getEventTriggerType() throws APIException {
return 1;
}
public String getEventSubscriberName() throws APIException {
return "事件订户名称";
}
public String getEventName() throws APIException {
return "文件发布流程邮件补发程序";
}
public String getEventHandlerName() throws APIException {
return "事件处理器";
}
public IDataObject getDataObject() throws APIException {
return data;
}
public IWorkflow getWorkFlow() throws APIException {
return null;
}
};
return event;
}
/**
* 创建一个测试用的状态变更事件<br>
*
* @param data 事件中的数据对象
* @return IEventInfo
* @author namelessmyth
* @since [2016年7月20日]
*/
public static IWFChangeStatusEventInfo createIWFChangeStatusEventInfo(final IDataObject obj) {
IWFChangeStatusEventInfo event = new IWFChangeStatusEventInfo() {
@Override
public void setUserDefinedMap(Map arg0) throws APIException {
}
@Override
public Map getUserDefinedMap() throws APIException {
return null;
}
@Override
public int getEventType() throws APIException {
return 0;
}
@Override
public int getEventTriggerType() throws APIException {
return 0;
}
@Override
public String getEventSubscriberName() throws APIException {
return null;
}
@Override
public String getEventName() throws APIException {
return null;
}
@Override
public String getEventHandlerName() throws APIException {
return null;
}
@Override
public IDataObject getDataObject() throws APIException {
return obj;
}
@Override
public IWorkflow getWorkFlow() throws APIException {
return null;
}
@Override
public void setUrgent(boolean arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public void setObservers(Collection arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public void setComments(String arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public void setApprovers(Collection arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public void setAcknowledgers(Collection arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public boolean isUrgent() throws APIException {
// TODO Auto-generated method stub
return false;
}
@Override
public ISignoffReviewer[] getObservers() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getComments() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public ISignoffReviewer[] getApprovers() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public ISignoffReviewer[] getAcknowledgers() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setNotifiers(Collection arg0) throws APIException {
// TODO Auto-generated method stub
}
@Override
public boolean isAutoPromote() throws APIException {
// TODO Auto-generated method stub
return false;
}
@Override
public IStatus getToStatus() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public IDataObject[] getNotifiers() throws APIException {
// TODO Auto-generated method stub
return null;
}
@Override
public IStatus getFromStatus() throws APIException {
// TODO Auto-generated method stub
return null;
}
};
return event;
}
}
新建单元测试用例
Eclipse
打开要测试的类上选择File->new,选择单元测试用例。然后next
?选择junit4,如果是第一次新建单元测试用例,eclipse会自动将junit4库加入到classpath里面。然后选择单元测试专用的源代码目录。
?构造入参,调用已经写好的doAction方法:
@Test
public void testDoActionIActionParam() throws Exception {
IAgileSession session = IAgileTestUtils.getSession("dev");
IItem change = (IItem)session.getObject(IItem.OBJECT_TYPE, "P00005");
IEventInfo event = IAgileTestUtils.createIUpdateEventInfo(change);
new AutoSetValueEvent().doAction(session, null, event);
}
然后在单元测试类里面右击选择debug as -> junit test 就可以调试程序了.
远程debug
环境准备
首先找一个没有人使用的环境,因为debug的时候会阻塞其他用户的操作。直到释放断点。
本文使用的Vmware本地虚拟机。网络适配器建议选择"NAT"和桥接模式。
注意:经测试“仅主机模式”是不行的。
在Agile的应用服务器目录中找到setDomainEnv.bat中开启debug选项。(具体的细节涉及信息安全不便贴出,需要的小伙伴可以联系我获取)。
然后进入到IDE的远程debug配置界面。本文以Eclipse为例:
启动远程debug模式。然后在环境中执行出触发程序的相关操作。就会进入到调试窗口了。
|