内容简介:在软件工程领域,无论对于前端或是后端工程师都必须对自己的代码质量负责,尤其是后端工程师,高度的单元测试覆盖率是最有效的手段之一。以Java代码为例,有着Junit、Mockito等开源单元测试框架,并且非常便于测试集成。Golang自身便带有单元测试模块,都是为提高软件质量而设计的,优秀的开源框架其单元测试覆盖率都非常高,才能为其软件质量提供保障。一名优秀的后端工程师必须具备编写单元测试的习惯,而且测试覆盖率越高你的软件质量也就越好,其次高度覆盖的测试用例方便软件的迭代与维护,能够有助于后者快速理解代码与定
image
在软件工程领域,无论对于前端或是后端工程师都必须对自己的代码质量负责,尤其是后端工程师,高度的单元测试覆盖率是最有效的手段之一。
以 Java 代码为例,有着Junit、Mockito等开源单元测试框架,并且非常便于测试集成。Golang自身便带有单元测试模块,都是为提高软件质量而设计的,优秀的开源框架其单元测试覆盖率都非常高,才能为其软件质量提供保障。
一名优秀的后端工程师必须具备编写单元测试的习惯,而且测试覆盖率越高你的软件质量也就越好,其次高度覆盖的测试用例方便软件的迭代与维护,能够有助于后者快速理解代码与定位问题。
高覆盖体现在测试用例覆盖public方法、函数中的if-else等逻辑、参数检查、内部定义等。
这里以Junit和Google的Truth为案例展示一个测试用例案例。
定义一个Resource实体类型,实体内部定义了参数必要检查、public函数:
/** * {@link Resource} represents a resource, which capture identifying information about the entities * for which signals (stats or traces) are reported. */ @Immutable @AutoValue public abstract class Resource { private static final int MAX_LENGTH = 255; private static final String ERROR_MESSAGE_INVALID_CHARS = " should be a ASCII string with a length greater than 0 and not exceed " + MAX_LENGTH + " characters."; private static final String ERROR_MESSAGE_INVALID_VALUE = " should be a ASCII string with a length not exceed " + MAX_LENGTH + " characters."; private static final Resource EMPTY = new AutoValue_Resource(Collections.emptyMap()); Resource() {} public static Resource getEmpty() { return EMPTY; } /** * Returns a map of labels that describe the resource. * * @return a map of labels. */ public abstract Map<String, String> getLabels(); /** * Returns a {@link Resource}. * * @param labels a map of labels that describe the resource. * @return a {@code Resource}. * @throws NullPointerException if {@code labels} is null. * @throws IllegalArgumentException if label key or label value is not a valid printable ASCII * string or exceed {@link #MAX_LENGTH} characters. */ public static Resource create(Map<String, String> labels) { checkLabels(labels); return new AutoValue_Resource(labels); } /** * Returns a new, merged {@link Resource} by merging the current {@code Resource} with the * {@code other} {@code Resource}. In case of a collision, current {@code Resource} takes * precedence. * * @param other the {@code Resource} that will be merged with {@code this}. * @return the newly merged {@code Resource}. */ public Resource merge(@Nullable Resource other) { if (other == null) { return this; } Map<String, String> mergedLabelMap = new LinkedHashMap<>(other.getLabels()); // Labels from resource overwrite labels from otherResource. for (Map.Entry<String, String> entry : this.getLabels().entrySet()) { mergedLabelMap.put(entry.getKey(), entry.getValue()); } return new AutoValue_Resource(mergedLabelMap); } private static void checkLabels(Map<String, String> labels) { for (Map.Entry<String, String> entry : labels.entrySet()) { Utils.checkArgument( isValidAndNotEmpty(entry.getKey()), "Label key" + ERROR_MESSAGE_INVALID_CHARS); Utils.checkArgument( isValid(entry.getValue()), "Label value" + ERROR_MESSAGE_INVALID_VALUE); } } /** * Determines whether the given {@code String} is a valid printable ASCII string with a length not * exceed {@link #MAX_LENGTH} characters. * * @param name the name to be validated. * @return whether the name is valid. */ private static boolean isValid(String name) { return name.length() <= MAX_LENGTH && StringUtils.isPrintableString(name); } /** * Determines whether the given {@code String} is a valid printable ASCII string with a length * greater than 0 and not exceed {@link #MAX_LENGTH} characters. * * @param name the name to be validated. * @return whether the name is valid. */ private static boolean isValidAndNotEmpty(String name) { return !name.isEmpty() && isValid(name); } }
为其提供高度覆盖的测试用例:
/** Unit tests for {@link Resource}. */ @RunWith(JUnit4.class) public final class ResourceTest { @Rule public final ExpectedException thrown = ExpectedException.none(); private static final Resource DEFAULT_RESOURCE = Resource.create(Collections.emptyMap()); private Resource resource1; private Resource resource2; @Before public void setUp() { Map<String, String> labelMap1 = new HashMap<>(); labelMap1.put("a", "1"); labelMap1.put("b", "2"); Map<String, String> labelMap2 = new HashMap<>(); labelMap2.put("a", "1"); labelMap2.put("b", "3"); labelMap2.put("c", "4"); resource1 = Resource.create(labelMap1); resource2 = Resource.create(labelMap2); } @Test public void create() { Map<String, String> labelMap = new HashMap<>(); labelMap.put("a", "1"); labelMap.put("b", "2"); Resource resource = Resource.create(labelMap); assertThat(resource.getLabels()).isNotNull(); assertThat(resource.getLabels().size()).isEqualTo(2); assertThat(resource.getLabels()).isEqualTo(labelMap); Resource resource1 = Resource.create(Collections.emptyMap()); assertThat(resource1.getLabels()).isNotNull(); assertThat(resource1.getLabels()).isEmpty(); } @Test public void testResourceEquals() { Map<String, String> labelMap1 = new HashMap<>(); labelMap1.put("a", "1"); labelMap1.put("b", "2"); Map<String, String> labelMap2 = new HashMap<>(); labelMap2.put("a", "1"); labelMap2.put("b", "3"); labelMap2.put("c", "4"); new EqualsTester() .addEqualityGroup(Resource.create(labelMap1), Resource.create(labelMap1)) .addEqualityGroup(Resource.create(labelMap2)) .testEquals(); } @Test public void testMergeResources() { Map<String, String> expectedLabelMap = new HashMap<>(); expectedLabelMap.put("a", "1"); expectedLabelMap.put("b", "2"); expectedLabelMap.put("c", "4"); Resource resource = DEFAULT_RESOURCE.merge(resource1).merge(resource2); assertThat(resource.getLabels()).isEqualTo(expectedLabelMap); } @Test public void testMergeResources_Resource1_Null() { Map<String, String> expectedLabelMap = new HashMap<>(); expectedLabelMap.put("a", "1"); expectedLabelMap.put("b", "3"); expectedLabelMap.put("c", "4"); Resource resource = DEFAULT_RESOURCE.merge(null).merge(resource2); assertThat(resource.getLabels()).isEqualTo(expectedLabelMap); } @Test public void testMergeResources_Resource2_Null() { Map<String, String> expectedLabelMap = new HashMap<>(); expectedLabelMap.put("a", "1"); expectedLabelMap.put("b", "2"); Resource resource = DEFAULT_RESOURCE.merge(resource1).merge(null); assertThat(resource.getLabels()).isEqualTo(expectedLabelMap); } @Test public void testCreateResources_ArgumentKey_Null() { Map<String, String> labelMap = new HashMap<>(); labelMap.put("a", "1"); labelMap.put(null, "2"); thrown.expect(NullPointerException.class); Resource.create(labelMap); } @Test public void testCreateResources_ArgumentKey_Unprintable() { Map<String, String> labelMap = new HashMap<>(); labelMap.put("a", "1"); labelMap.put("\2b\3", "2"); thrown.expect(IllegalArgumentException.class); Resource.create(labelMap); } }
以上所述就是小编给大家介绍的《提高单元测试用例覆盖率》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- C++语言的单元测试与代码覆盖率
- James Shore:不要使用单元测试的代码覆盖率
- 使用 PHPUnit 进行单元测试并生成代码覆盖率报告
- 从单元测试覆盖率看富领域模型到底有多富
- iOS 覆盖率检测原理与增量代码测试覆盖率工具实现
- 聊聊前端代码覆盖率
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Four
Scott Galloway / Portfolio / 2017-10-3 / USD 28.00
NEW YORK TIMES BESTSELLER USA TODAY BESTSELLER Amazon, Apple, Facebook, and Google are the four most influential companies on the planet. Just about everyone thinks they know how they got there.......一起来看看 《The Four》 这本书的介绍吧!