Rob*_*ino 23 java eclipse junit unit-testing
我正在寻找以下内容:
null价值观这是一个人为的例子来展示一些技巧.
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import com.google.common.collect.ImmutableList;
public class MyPath {
  public static final MyPath ROOT = MyPath.ofComponents("ROOT");
  public static final String SEPARATOR = "/";
  public static MyPath ofComponents(String... components) {
    checkNotNull(components);
    checkArgument(components.length > 0);
    checkArgument(!Arrays.asList(components).contains(""));
    return new MyPath(components);
  }
  private final ImmutableList<String> components;
  private MyPath(String[] components) {
    this.components = ImmutableList.copyOf(components);
  }
  public ImmutableList<String> getComponents() {
    return components;
  }
  @Override
  public String toString() {
    StringBuilder stringBuilder = new StringBuilder();
    for (String pathComponent : components) {
      stringBuilder.append("/" + pathComponent);
    }
    return stringBuilder.toString();
  }
}
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsEmptyCollection.empty;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import com.google.common.base.Joiner;
@RunWith(Enclosed.class)
public class MyPathTests {
  public static class GetComponents {
    @Test
    public void componentsCorrespondToFactoryArguments() {
      String[] components = { "Test1", "Test2", "Test3" };
      MyPath myPath = MyPath.ofComponents(components);
      assertThat(myPath.getComponents(), contains(components));
    }
  }
  public static class OfComponents {
    @Test
    public void acceptsArrayOfComponents() {
      MyPath.ofComponents("Test1", "Test2", "Test3");
    }
    @Test
    public void acceptsSingleComponent() {
      MyPath.ofComponents("Test1");
    }
    @Test(expected = IllegalArgumentException.class)
    public void emptyStringVarArgsThrows() {
      MyPath.ofComponents(new String[] { });
    }
    @Test(expected = NullPointerException.class)
    public void nullStringVarArgsThrows() {
      MyPath.ofComponents((String[]) null);
    }
    @Test(expected = IllegalArgumentException.class)
    public void rejectsInterspersedEmptyComponents() {
      MyPath.ofComponents("Test1", "", "Test2");
    }
    @Test(expected = IllegalArgumentException.class)
    public void rejectsSingleEmptyComponent() {
      MyPath.ofComponents("");
    }
    @Test
    public void returnsNotNullValue() {
      assertThat(MyPath.ofComponents("Test"), is(notNullValue()));
    }
  }
  public static class Root {
    @Test
    public void hasComponents() {
      assertThat(MyPath.ROOT.getComponents(), is(not(empty())));
    }
    @Test
    public void hasExactlyOneComponent() {
      assertThat(MyPath.ROOT.getComponents(), hasSize(1));
    }
    @Test
    public void hasExactlyOneInboxComponent() {
      assertThat(MyPath.ROOT.getComponents(), contains("ROOT"));
    }
    @Test
    public void isNotNull() {
      assertThat(MyPath.ROOT, is(notNullValue()));
    }
    @Test
    public void toStringIsSlashSeparatedAbsolutePathToInbox() {
      assertThat(MyPath.ROOT.toString(), is(equalTo("/ROOT")));
    }
  }
  public static class ToString {
    @Test
    public void toStringIsSlashSeparatedPathOfComponents() {
      String[] components = { "Test1", "Test2", "Test3" };
      String expectedPath =
          MyPath.SEPARATOR + Joiner.on(MyPath.SEPARATOR).join(components);
      assertThat(MyPath.ofComponents(components).toString(),
          is(equalTo(expectedPath)));
    }
  }
  @Test
  public void testPathCreationFromComponents() {
    String[] pathComponentArguments = new String[] { "One", "Two", "Three" };
    MyPath myPath = MyPath.ofComponents(pathComponentArguments);
    assertThat(myPath.getComponents(), contains(pathComponentArguments));
  }
}
是否有用于构建单元测试的技术列表?比我上面的过度简化列表更先进的东西(例如检查空值,检查边界,检查预期的异常等)可能在书中购买或访问URL?
一旦我有一个采用某种类型参数的方法,我可以获得任何Eclipse插件来为我的测试生成存根吗?也许使用Java Annotation指定有关方法的元数据并让工具为我实现相关的检查?(例如@MustBeLowerCase,@ShouldBeOfSize(n = 3),...)
我发现它需要记住所有这些"质量检查技巧"和/或应用它们一样乏味和机器人一样,我发现它很容易复制和粘贴,而且当我像我一样编写代码时,我发现它不能自我记录以上.不可否认,Hamcrest 库专注于测试类型的一般方向(例如,使用RegEx,在File对象上使用String对象等),但显然不会自动生成任何测试存根,也不会反映代码及其属性并准备我的安全带.
请帮我把它做得更好.
不要告诉我,我只是提供代码,这是一个愚蠢的包装,围绕从静态工厂方法提供的路径步骤列表中创建路径的概念,这是一个完全组成的例子,但它显示"少数"论证验证的案例......如果我包含更长的例子,谁会真正阅读这篇文章?
考虑使用ExpectedException而不是@Test(expected....这是因为,例如,如果您期望a NullPointerException并且您的测试在您的设置中抛出此异常(在调用测试方法之前),您的测试将通过.随着ExpectedException你在调用被测方法之前就把期望放在一边,所以没有机会这样做.此外,ExpectedException允许您测试异常消息,如果您有两个IllegalArgumentExceptions可能被抛出的异常消息并且需要检查正确的异常消息.
考虑将您的测试方法与设置和验证隔离开来,这样可以简化测试审查和维护.当被测试类中的方法作为设置的一部分被调用时,尤其如此,这可能会混淆哪个是被测试的方法.我使用以下格式:
public void test() {
   //setup
   ...
   // test (usually only one line of code in this block)
   ...
   //verify
   ...
}
Clean Code有一个很好的测试部分
我见过的大多数示例(包括Eclipse自动生成的)在测试标题中都有测试方法.这有助于审查和维护.例如:testOfComponents_nullCase.你的例子是我见过的第一个Enclosed通过测试方法使用to group方法,这非常好.但是,它会增加一些开销,@Before并且@After不会在封闭的测试类之间共享.
我还没有开始使用它,但是Guava有一个测试库:guava-testlib.我没有机会玩它,但似乎有一些很酷的东西.例如:NullPointerTest是引用:
- 一个测试实用程序,用于验证您的方法在其任何*参数为null时抛出{@link*NullPointerException}或{@link UnsupportedOperationException}.要使用它,必须首先为类使用的参数类型提供有效的默认值*.
回顾:我意识到上面的测试仅仅是一个例子,但由于建设性的评论可能会有所帮助,所以你走了.
在测试中getComponents,也测试空列表情况.另外,使用IsIterableContainingInOrder.
在测试中ofComponents,似乎调用getComponents或toString验证它是否正确处理了各种非错误情况是有意义的.应该有一个没有传递参数的测试ofComponents.我知道这已经完成,ofComponents( new String[]{})但为什么不ofComponents()呢?需要测试哪里null是传递的值之一:ofComponents("blah", null, "blah2")因为这将抛出NPE.
在测试中ROOT,正如之前所指出的,我建议调用ROOT.getComponents一次并对其进行所有三次验证.此外,ItIterableContainingInOrder所有三个都不是空的,大小和包含.将is在测试是extraineous(虽然它是语言),我觉得是不值得拥有(恕我直言)
在测试中toString,我觉得隔离测试方法非常有帮助.我会写toStringIsSlashSeparatedPathOfComponents如下.请注意,我不使用被测试类中的常量.这是因为恕我直言,对被测试类的任何功能改变都会导致测试失败.
@Test     
public void toStringIsSlashSeparatedPathOfComponents() {       
   //setup 
   String[] components = { "Test1", "Test2", "Test3" };       
   String expectedPath =  "/" + Joiner.on("/").join(components);   
   MyPath path = MyPath.ofComponents(components)
   // test
   String value = path.toStrign();
   // verify
   assertThat(value, equalTo(expectedPath));   
} 
Enclosed不会运行任何不在内部类中的单元测试.因此testPathCreationFromComponents不会运行.
最后,使用测试驱动开发.这将确保您的测试通过正确的原因,并将按预期失败.