【问题标题】:How to unit test package dependencies in Scala?如何在 Scala 中对包依赖项进行单元测试?
【发布时间】:2023-04-06 20:18:01
【问题描述】:

在我的 Scala 项目中,我有一个非常广泛和深入的类和包层次结构。显然我希望将包的依赖关系保持在最低限度。

我不知道我是否可以为此使用编译器, 所以我想知道如何使用单元测试来验证包的独立性?

PS:由于我使用的是 Scala,而不是 Java,因此该方法可能应该适用于字节码级别。

【问题讨论】:

    标签: unit-testing scala dependencies


    【解决方案1】:

    这不能通过单元测试来完成,但编译器是你的朋友。使用 private[PACKAGENAME] 使类仅在包内可见。与 Java 不同,该类在子包中也可见。

    【讨论】:

    • 好点!与静态类型一样,强制执行比临时测试更好。
    • 是的,但这只能部分解决一般情况。一般的依赖约束解决方案将允许表达诸如“库 foo 仅由包 bar 和 baz 中的类使用”和“模块 bar 和 baz 之间的所有依赖项都是抽象的,而不是具体的”这样的要求。
    【解决方案2】:

    我强烈推荐Classycle。它适用于我的混合 Scala/Java 项目。它在字节码级别工作,我从未遇到过与 Scala 相关的问题。

    在小型项目中,您可以手动编写配置文件。我们的项目很大,所以我编写了一个 Scala 脚本来生成配置文件。生成每个包的文件部分如下所示:

    [agent] = org.nlogo.agent.* excluding org.nlogo.agent.*.*
    [agent+] = [agent] [api+]
    [agent-] = org.nlogo.* excluding [agent+]
    check [agent] independentOf [agent-]
    

    这表示 org.nlogo.agent 可能依赖于 org.nlogo.api(并递归地依赖于 org.nlogo.api 允许的依赖项),但不依赖于其他包。

    您还可以编写检查外部依赖项的规则,例如以下是我检查我们是否仅依赖某些特定包中的 JOGL 的方法:

    [JOGL-free-zone] = org.nlogo.* excluding [gl.render] [gl.view]
    [JOGL] = net.java.games.* javax.media.opengl.*
    check [JOGL-free-zone] independentOf [JOGL]
    

    【讨论】:

    • 听起来棒极了 - 我要试试这个。
    【解决方案3】:

    我玩过 JDepend ,但没有在愤怒中使用它。它允许您设置包和类依赖约束,并使用 JUnit 测试对其进行验证。它还具有大量功能,可用于查找依赖循环、计算大量指标,并通常保持您的架构干净、闪亮和新鲜。

    【讨论】:

    • 对,我想我也用过一次 JDepend ——但这是一次可怕的经历,我记得包名比较和部分字符串匹配有很多问题......
    【解决方案4】:

    scala 编译器可以为您生成依赖关系图,然后您可以使用自制工具对其进行检查。你可以这样称呼它:

    scalac -make:transitive -dependencyfile dep.txt *.scala
    

    它会产生什么:

    .;C:\Progra~2\Java\jre6\lib\ext\QTJava.zip;C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip
    -------
    Aposta.scala -> Aposta.scala
    Aposta.scala -> Premio.scala
    Aposta.scala -> Bilhete.scala
    Premio.scala -> Premio.scala
    Premio.scala -> Sorteio.scala
    Bilhete.scala -> Aposta.scala
    Bilhete.scala -> Bilhete.scala
    Bilhete.scala -> Sorteio.scala
    Browser.scala -> Browser.scala
    Megasena.scala -> Browser.scala
    Megasena.scala -> Bilhete.scala
    Megasena.scala -> Sorteio.scala
    Megasena.scala -> Megasena.scala
    Sorteio.scala -> Premio.scala
    Sorteio.scala -> Sorteio.scala
    -------
    Aposta.scala -> megasena\Aposta$.class
    Aposta.scala -> megasena\Aposta$$anonfun$1.class
    Aposta.scala -> megasena\Aposta$$anonfun$toString$1.class
    Aposta.scala -> megasena\Aposta$$anonfun$toString$2.class
    Aposta.scala -> megasena\Aposta.class
    Premio.scala -> megasena\Premio$.class
    ...
    

    此外,sbt 会自动执行此操作(在目标目录中查找名为 analysis/dependencies 的文件以及 analysis/external)。这就是他们的样子:

    #Source Dependencies
    #Mon Jan 04 18:31:56 BRST 2010
    Sorteio.scala=Megasena.scala;Premio.scala;Bilhete.scala
    Premio.scala=Sorteio.scala;Aposta.scala
    Browser.scala=Megasena.scala
    Aposta.scala=Bilhete.scala
    Bilhete.scala=Megasena.scala;Aposta.scala
    Megasena.scala=
    RedBlackTree.scala=
    

    #External Dependencies
    #Mon Jan 04 18:31:56 BRST 2010
    C\:\\Workset\\megasena\\project\\boot\\scala-2.7.4\\lib\\scala-library.jar=Browser.scala;RedBlackTree.scala;Premio.scala
    ;Bilhete.scala;Sorteio.scala;Megasena.scala;Aposta.scala
    C\:\\Arquivos\ de\ programas\\Java\\jdk1.6.0_16\\jre\\lib\\rt.jar=Browser.scala;RedBlackTree.scala;Premio.scala;Bilhete.
    scala;Sorteio.scala;Megasena.scala;Aposta.scala
    

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多