对于 IntelliJ/Cursive,为什么 clojure.test.is 认为空字符串等于任何字符串?
With IntelliJ/Cursive, why does clojure.test.is consider that empty-string equals any string?
使用 Intellij(v.2021.3.2)和 Cursive(v.1.12.1-2021.3)“运行 测试”功能(测试或命名空间上的绿色 运行 箭头), Clojure 中的一个简单单元测试在发现 "X"
等于 ""
.
时通过
完整示例:
(ns my-test
(:require [clojure.test :refer [deftest is run-tests]]))
(deftest compare-empty
(is (= "X" "")))
- 如果我将
""
替换为 "Y"
,单元测试系统将按预期工作。
- 即使在最小的项目中也会出现此问题:我使用“裸项目”向导创建一个新项目,可选择将
src
重命名为 test
,添加此文件,然后单击 运行箭头.
- 如果我直接添加
(run-tests)
和 运行 这个脚本(作为“应用程序”,那么这正确地失败了。
- 问题发生在直接从 Exercism 拉取的项目中。
- 出现问题
- 如果我使用 Leinengen
project.clj
。
- 如果我删除它并使用 the
deps.edn
file。
- 如前所述,两者都没有。
- 或者如果我将
deps.edn
添加到裸项目,然后将其重新加载为 Deps 项目。
- Clojure 1.10 和 1.11 会出现此问题。
前言
首先,我总是建议从命令行 运行ning 测试,而不是从 IDE
可能的原因和解决方案
一个测试很容易不小心成为运行。总是困扰我的一种常见方式是,如果我不小心 re-used 两次不同的测试使用相同的名称。就像 Clojure Var
一样,第二个将替换第一个声明。
下面的测试如果是运行肯定会失败,看起来像:
(deftest t-string
(is (= "X" "")))
结果
> lein clean ; lein test
--------------------------------------
Clojure 1.11.1 Java 1.8.0_322
--------------------------------------
Testing tst.demo.core
FAIL in (t-string) (core.clj:11)
expected: (= "X" "")
actual: (not (= "X" ""))
Testing tst.demo.other
Ran 3 tests containing 4 assertions.
1 failures, 0 errors.
Failed 1 of 4 assertions
此外,请注意在 re-running 之前始终“清理”很重要,因为错误有时会使您使用与最新源代码不同的旧编译字节码。我为此使用别名:
alias lct='time (lein do clean, test)'
但是,考虑剪切和粘贴错误:
(deftest t-string
(is (= "X" "")))
(deftest t-string
(is (= "X" "X")))
结果
> lein clean ; lein test
:reloading (tst.demo.core)
Testing _bootstrap
--------------------------------------
Clojure 1.11.1 Java 1.8.0_322
--------------------------------------
Testing tst.demo.core
Testing tst.demo.other
Ran 3 tests containing 4 assertions.
0 failures, 0 errors.
改进的解决方案
因此,您可能对扩展库 tupelo.test
感兴趣(有关示例,请参见 this template project)。它将 auto-generate 唯一的测试名称,所以你可以这样写代码:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(is= "X" ""))
(dotest
(is= "X" "X"))
结果
lein test tst.demo.core
lein test :only tst.demo.core/dotest-line-4
FAIL in (dotest-line-4) (core.clj:5)
expected: (clojure.core/= "X" "")
actual: (not (clojure.core/= "X" ""))
lein test tst.demo.other
Ran 4 tests containing 5 assertions.
1 failures, 0 errors.
Tests failed.
( lein do clean, test; ) 36.72s user 1.73s system 308% cpu 12.474 total
另请注意,tupelo.test
包括 is=
、isnt=
和
等便利功能
(is-nonblank= "hello " " hello") ; => true
根据 OP 的说法,升级到最新的 Cursive 版本(在他们的例子中是 1.12.3-2021.3)解决了这个问题。
使用 Intellij(v.2021.3.2)和 Cursive(v.1.12.1-2021.3)“运行 测试”功能(测试或命名空间上的绿色 运行 箭头), Clojure 中的一个简单单元测试在发现 "X"
等于 ""
.
完整示例:
(ns my-test
(:require [clojure.test :refer [deftest is run-tests]]))
(deftest compare-empty
(is (= "X" "")))
- 如果我将
""
替换为"Y"
,单元测试系统将按预期工作。 - 即使在最小的项目中也会出现此问题:我使用“裸项目”向导创建一个新项目,可选择将
src
重命名为test
,添加此文件,然后单击 运行箭头. - 如果我直接添加
(run-tests)
和 运行 这个脚本(作为“应用程序”,那么这正确地失败了。 - 问题发生在直接从 Exercism 拉取的项目中。
- 出现问题
- 如果我使用 Leinengen
project.clj
。 - 如果我删除它并使用 the
deps.edn
file。 - 如前所述,两者都没有。
- 或者如果我将
deps.edn
添加到裸项目,然后将其重新加载为 Deps 项目。
- 如果我使用 Leinengen
- Clojure 1.10 和 1.11 会出现此问题。
前言
首先,我总是建议从命令行 运行ning 测试,而不是从 IDE
可能的原因和解决方案
一个测试很容易不小心成为运行。总是困扰我的一种常见方式是,如果我不小心 re-used 两次不同的测试使用相同的名称。就像 Clojure Var
一样,第二个将替换第一个声明。
下面的测试如果是运行肯定会失败,看起来像:
(deftest t-string
(is (= "X" "")))
结果
> lein clean ; lein test
--------------------------------------
Clojure 1.11.1 Java 1.8.0_322
--------------------------------------
Testing tst.demo.core
FAIL in (t-string) (core.clj:11)
expected: (= "X" "")
actual: (not (= "X" ""))
Testing tst.demo.other
Ran 3 tests containing 4 assertions.
1 failures, 0 errors.
Failed 1 of 4 assertions
此外,请注意在 re-running 之前始终“清理”很重要,因为错误有时会使您使用与最新源代码不同的旧编译字节码。我为此使用别名:
alias lct='time (lein do clean, test)'
但是,考虑剪切和粘贴错误:
(deftest t-string
(is (= "X" "")))
(deftest t-string
(is (= "X" "X")))
结果
> lein clean ; lein test
:reloading (tst.demo.core)
Testing _bootstrap
--------------------------------------
Clojure 1.11.1 Java 1.8.0_322
--------------------------------------
Testing tst.demo.core
Testing tst.demo.other
Ran 3 tests containing 4 assertions.
0 failures, 0 errors.
改进的解决方案
因此,您可能对扩展库 tupelo.test
感兴趣(有关示例,请参见 this template project)。它将 auto-generate 唯一的测试名称,所以你可以这样写代码:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(is= "X" ""))
(dotest
(is= "X" "X"))
结果
lein test tst.demo.core
lein test :only tst.demo.core/dotest-line-4
FAIL in (dotest-line-4) (core.clj:5)
expected: (clojure.core/= "X" "")
actual: (not (clojure.core/= "X" ""))
lein test tst.demo.other
Ran 4 tests containing 5 assertions.
1 failures, 0 errors.
Tests failed.
( lein do clean, test; ) 36.72s user 1.73s system 308% cpu 12.474 total
另请注意,tupelo.test
包括 is=
、isnt=
和
(is-nonblank= "hello " " hello") ; => true
根据 OP 的说法,升级到最新的 Cursive 版本(在他们的例子中是 1.12.3-2021.3)解决了这个问题。