【问题标题】:How to provide data files for android unit tests如何为android单元测试提供数据文件
【发布时间】:2012-04-11 12:30:41
【问题描述】:

我正在开发使用 Android 的 java.xml.parsers.DocumentBuilder 和 DocumentBuilderFactory 实现从 XML 文件加载信息的软件。我正在为我的对象编写单元测试,我需要能够提供各种 xml 文件来执行被测代码。我正在使用 Eclipse 并且有一个单独的 Android 测试项目。我找不到将测试 xml 放入测试项目的方法,以便被测代码可以打开文件。

  • 如果我把文件放在测试项目的/assets下,被测代码看不到。
  • 如果我将文件放在被测代码的 /assets 中,它当然可以看到这些文件,但现在我的实际系统中只包含测试数据文件。
  • 如果我将文件手动复制到 /sdcard/data 目录,我可以从被测代码中打开它们,但这会干扰我的测试自动化。

任何关于如何让不同的 xml 测试文件驻留在测试包中但对被测代码可见的建议将不胜感激。

这是我尝试构建单元测试的方式:

public class AppDescLoaderTest extends AndroidTestCase
{
  private static final String SAMPLE_XML = "sample.xml";

  private AppDescLoader       m_appDescLoader;
  private Application         m_app;

  protected void setUp() throws Exception
  {
    super.setUp();
    m_app = new Application();
    //call to system under test to load m_app using
    //a sample xml file
    m_appDescLoader = new AppDescLoader(m_app, SAMPLE_XML, getContext());
  }

  public void testLoad_ShouldPopulateDocument() throws Exception
  {
    m_appDescLoader.load();

  }    
}

这不起作用,因为 SAMPLE_XML 文件在测试的上下文中,但 AndroidTestCase 为被测系统提供了一个上下文,它无法从测试包中看到资产。

这是根据给出的答案工作的修改后的代码:

public class AppDescLoaderTest extends InstrumentationTestCase
{
   ...
  protected void setUp() throws Exception
  {
    super.setUp();
    m_app = new Application();
    //call to system under test to load m_app using
    //a sample xml file
     m_appDescLoader = new AppDescLoader(m_app, SAMPLE_XML, getInstrumentation().getContext());
  }

【问题讨论】:

    标签: android xml unit-testing junit3


    【解决方案1】:

    选项 1:使用InstrumentationTestCase

    假设您在 android 项目和测试项目中都有 assets 文件夹,并且您将 XML 文件放在 assets 文件夹中。在测试项目下的测试代码中,这将从 android 项目资产文件夹中加载 xml:

    getInstrumentation().getTargetContext().getResources().getAssets().open(testFile);
    

    这将从测试项目资产文件夹中加载 xml:

    getInstrumentation().getContext().getResources().getAssets().open(testFile);
    

    选项 2:使用ClassLoader

    在您的测试项目中,如果将assets文件夹添加到项目构建路径(这是在r14版本之前由ADT插件自动完成的),您可以在没有上下文的情况下从res或assets目录(即项目构建路径下的目录)加载文件:

    String file = "assets/sample.xml";
    InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
    

    【讨论】:

    • 谢谢。这行得通,只有我首先必须将我的测试用例更改为 InstrumentationTestCase。
    • 我已经修改了我的问题以显示有效的代码。感谢您的帮助。
    • +1 用于选项 2。刚刚在 res 级别添加了一个资产目录,并且新代码在 Android Studio 构建中“正常工作”。无需纠结构建路径。
    • 使用android studio时,资产不在单独的项目中,可能会放在原应用的包中(所以使用目标上下文)。对于 eclipse 和单独的项目,很有可能应该使用测试项目上下文。
    • 那么大的问题是当我编译发布时如何不部署这些?为什么 android 不能有一个测试资产文件夹,而不是发布不出去?
    【解决方案2】:

    对于 Android 和 JVM 单元测试,我使用以下内容:

    public final class DataStub {
        private static final String BASE_PATH = resolveBasePath(); // e.g. "./mymodule/src/test/resources/";
    
        private static String resolveBasePath() {
            final String path = "./mymodule/src/test/resources/";
            if (Arrays.asList(new File("./").list()).contains("mymodule")) {
                return path; // version for call unit tests from Android Studio
            }
            return "../" + path; // version for call unit tests from terminal './gradlew test'
        }
    
        private DataStub() {
            //no instances
        }
    
        /**
         * Reads file content and returns string.
         * @throws IOException
         */
        public static String readFile(@Nonnull final String path) throws IOException {
            final StringBuilder sb = new StringBuilder();
            String strLine;
            try (final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"))) {
                while ((strLine = reader.readLine()) != null) {
                    sb.append(strLine);
                }
            } catch (final IOException ignore) {
                //ignore
            }
            return sb.toString();
        }
    }
    

    我放入下一个路径的所有原始文件:".../project_root/mymodule/src/test/resources/"

    【讨论】:

    • 你能展示你的测试类在访问这些方法时的样子吗?
    【解决方案3】:

    在 Kotlin 上试试这个:

    val json = File("src\\main\\assets\\alphabets\\alphabets.json").bufferedReader().use { it.readText() }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      • 1970-01-01
      • 1970-01-01
      • 2016-11-29
      • 1970-01-01
      • 2010-09-10
      • 2014-02-14
      相关资源
      最近更新 更多