如何在不重复测试代码的情况下以编程方式测试UI操作/活动?

时间:2016-09-24 10:19:57

标签: android unit-testing automated-tests android-espresso android-testing

我对TDD很新,特别是做TFD。我还没有编写任何代码,我想在与TDD一起开发所有内容之前先编写一个测试。我想要你的见解。我似乎是复制粘贴我的测试代码。我为我练习了'伪'用户故事。我要解释一下,因为这是一个真正的个人项目所以请耐心等待。

  

“用户可以搜索标签”

我有一个允许添加和搜索标签的UI。我使用最小的设计使它有点保守。我有一个按钮,可以在添加/搜索字符串之间切换。我有一个CardView代表这个,CardView是列表的一部分(就像Facebook一样)。现在我想测试一下,当用户按下按钮时,该卡上的内容将变为搜索模式。我几乎已经知道如何做到这一点,但每次测试复制粘贴我的测试代码有点困扰我。

这是我的测试:

public class TagListActivityTest
{
    @Test
    public void shouldHaveAddTagCard()
    {
        // User tapped to expand the card
        onView(withId(R.id.edittext_description_minimized))
                .perform(click());

        // User sees the expanded card
        onView(withId(R.id.linearlayout_add_note_maximize))
                .check(matches(isDisplayed()));

        // User sees the expanded card's quick action buttons
        onView(withId(R.id.relativelayout_quick_action_button))
                .check(matches(isDisplayed()));

        // User clicks the add tag button
        onView(withId(R.id.imagebutton_tag))
                .perform(click());

        // User sees the tag list
        onView(withId(R.id.coordinatorlayout_tag_list))
                .check(matches(isDisplayed()));

        // User sees the add tag card
        onView(withId(R.id.cardview_add_tag))
                .check(matches(isDisplayed()));
    }

    @Test
    public void shouldToggleToSearch()
    {
        // I am going to do the exact same thing as shouldHaveAddTagCard
        // starting from my parent activity until here...
        onView(withId(R.id.edittext_description_minimized))
                .perform(click());

        onView(withId(R.id.linearlayout_add_note_maximize))
                .check(matches(isDisplayed()));

        onView(withId(R.id.relativelayout_quick_action_button))
                .check(matches(isDisplayed()));

        onView(withId(R.id.imagebutton_tag))
                .perform(click());

        onView(withId(R.id.coordinatorlayout_tag_list))
                .check(matches(isDisplayed()));
    }
}

TagListActivity来自父活动。在你完成TagListActivity并且我已经为它编写测试之前,你必须做一些事情。因此,当我测试TagListActivity时,我必须首先在应用程序的主屏幕中进行导航,然后从我的测试过程shouldHaveAddTagCard中看到。这是我的问题,我必须一遍又一遍地写这个程序。因此,当我想测试shouldToggleSearch时,我必须从父活动开始并再次编写这些测试,直到我到达TagListActivity。我想我做错了什么。

所以我的问题是:

  1. 如果有已知的用户操作过程,我该如何组织此操作。 我已经为每个程序编写了测试,以确保它能够满足我的需求 待。
  2. 没有。 1让我觉得我在做什么有什么不对。我正在测试每个操作(即用户添加标记,用户搜索标记,用户删除标记)。所以前程序 我之前user can add tagsuser can search tag相同,我做过 在我实际测试之前复制粘贴那些前程序。
  3. 此外,我似乎无法按照here讨论的测试方法调用测试方法。我正在考虑重用测试代码,但这是不可取的。

    我做得对吗?有什么想法吗?

1 个答案:

答案 0 :(得分:1)

老实说,如果这是你第一次做TDD,那么你的测试看起来非常好。

减少重复

您可以使用@Before注释在每次测试之前执行一些代码。在您的情况下,它可能看起来像这样:

// this method will be executed before each test
@Before
public void clickOnEditTextDescription() {
    onView(withId(R.id.edittext_description_minimized))
            .perform(click());
    // put as much set up code in here as you need
}

请记住,通常,您不应在@Before方法中进行任何断言。它仅用于设置代码。

但它总是一件好事吗?

@Before方法很棒,但请记住,复制和粘贴测试代码并不总是坏事。这与生产代码有着不同的平衡。在生产代码中,您不需要重复,因为任何给定的业务逻辑应该只存在于一个位置。但是,在测试代码中,每个测试都需要完全独立于所有其他测试。如果在测试代码中删除 all 重复,那么在不破坏所有测试的情况下更改共享代码将非常困难。此外,您的测试将更难阅读,因为您必须继续引用共享代码。

我建议您对DAMP(描述性和有意义的短语)与DRY(不要重复自己)进行一些研究。 DAMP与单元测试更相关,并允许您有时重复自己。 DRY与生产代码更相关。以下答案很好地解释了这一点:

https://stackoverflow.com/a/11837973/6816469