单元测试数据结构的内部状态

efr*_*itz 8 java unit-testing data-structures

我的任务是为大量度量数据结构(即四叉树kd树变体)创建实现.我有大约四个这样的实现,但我目前测试的方式不是,因为我缺乏一个更好的词,好.

我需要一种干净的方法来测试从这些树/特里结构中插入和删除数据的方式,我可以测试节点的内部结构(检查父节点,子节点,排序等).这些实现以下独立的正确性证明和运行分析,所以我需要确保不仅是一个节点正确插入(意味着,从树上以后检索),而且在树上的一个很"正确"的位置.

然而,"单元测试"似乎是错误的方法,因为如果我没有弄错的话,它的目的是测试结构或系统的外部API.我见过很多的单元测试相关的问题问"我如何才能进入私人领域的单元测试"或"我怎么测试一个非公开的方法的返回值",得到的回答一般是"不要" t" - 我同意这个答案.

因此,我不会让任何愿意帮助的人只是模糊的ramblings,我的树实现的接口如下(基于java集合的Map接口):

public interface SpatialMap<K, V> extends Iterable<SpatialMap.Entry<K, V>>
{
// Query Operations

/**
 * Returns the number of key-value mappings in this map. If the map contains more than
 * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>.
 * 
 * @return The number of key-value mappings in this map.
 */
int size();

/**
 * Returns <tt>true</tt> if this map contains no key-value mappings.
 * 
 * @return <tt>true</tt> if this map contains no key-value mappings.
 */
boolean isEmpty();

/**
 * Returns <tt>true</tt> if this map contains a mapping for the specified key.
 * 
 * @param key
 *            The key whose presence in this map is to be tested.
 * @return <tt>true</tt> if this map contains a mapping for the specified key.
 */
boolean containsKey(K key);

/**
 * Returns the value to which the specified key is mapped, or {@code null} if this map contains
 * no mapping for the key.
 * 
 * <p>A return value of {@code null} does not <i>necessarily</i> indicate that the map contains
 * no mapping for the key; it's also possible that the map explicitly maps the key to
 * {@code null}. The {@link #containsKey containsKey} operation may be used to distinguish these
 * two cases.
 * 
 * @see #put(Comparable, Comparable, Object)
 * 
 * @param key
 *            The key whose associated value is to be returned.
 * @return The value to which the specified key is mapped, or {@code null} if this map contains
 *         no mapping for the key.
 */
V get(K key);

// Modification Operations

/**
 * Associates the specified value with the specified key in this map. If the map previously
 * contained a mapping for the key, the old value is replaced.
 * 
 * @param key
 *            The key with which the specified value is to be associated.
 * @param data
 *            The value to be associated with the specified key.
 * @return The previous value associated with the key, or <tt>null</tt> if there was no mapping
 *         for the key. (A <tt>null</tt> return can also indicate that the map previously
 *         associated <tt>null</tt> with <tt>key</tt>.)
 */
V put(K key, V data);

/**
 * Removes the mapping for the specified key from this map if present.
 * 
 * @param key
 *            The key whose mapping is to be removed from the map.
 * @return The previous value associated with the key, or <tt>null</tt> if there was no mapping
 *         for the key. (A <tt>null</tt> return can also indicate that the map previously
 *         associated <tt>null</tt> with <tt>key</tt>.)
 */
V remove(K key);

// Bulk Operations

/**
 * Removes all of the mappings from this map. The map will be empty after this call returns.
 */
void clear();
}
Run Code Online (Sandbox Code Playgroud)

这使得使用公共方法进行测试变得困难,因为我需要公共接口无法获得的某些数据(子/父指针).此外,在特里结构(PR四叉树,PRKDTree,MX变种等)具有从数据中分离,所以创建一个返回"节点"的公共方法节点也将被太远抽象,让我正确的数据.

我在寻找什么类型的测试方法(或者我可以使用JUnit的技术而不是我正在破坏美丽的认知界限)?

Jef*_*rey 5

有这样的情况,有时您确实需要测试结构的内部状态.在这种情况下,我将使用反射访问内部变量.有一些JUnit插件(PrivateAccessor http://junit-addons.sourceforge.net/junitx/util/PrivateAccessor.html)使这更容易.

权衡是你的测试会更加脆弱,因为如果内部状态发生变化,那么你的测试可能会中断.但是如果你想要确信你的内部状态是正确的,有时你需要这样做.

  • 是的,但如果变量名称发生变化,则测试可能会中断.这更像是一个白盒单元测试(与黑盒相反).有时这种风格是合适的,听起来就像你的情况,它正是你在寻找的. (2认同)