Testing 是否可以在Julia中组织健全性检查,以便在加载包时易于编译?

Testing 是否可以在Julia中组织健全性检查,以便在加载包时易于编译?,testing,julia,assert,flags,code-organization,Testing,Julia,Assert,Flags,Code Organization,我正在开发一个程序包,它需要快速运行并保持正确。我只想写一个函数,但这个函数有两个“版本”:一个在检测到任何有趣的业务时立即停止,另一个运行速度尽可能快。我的想法是在输入的随机样本上运行函数的严格版本,如果没有失败,则在整个输入集上运行快速版本。我肯定没有足够的计算能力对每一个输入都进行检查,即使我可以睡得更舒服。(我认为这已经是解决验证问题的错误方法,因此如果您有更好的组织方法,请随时提出建议,而不是对下面的问题进行具体改进。) 到目前为止,我已经找到了这个问题的临时解决方案,如下所示: mo

我正在开发一个程序包,它需要快速运行并保持正确。我只想写一个函数,但这个函数有两个“版本”:一个在检测到任何有趣的业务时立即停止,另一个运行速度尽可能快。我的想法是在输入的随机样本上运行函数的严格版本,如果没有失败,则在整个输入集上运行快速版本。我肯定没有足够的计算能力对每一个输入都进行检查,即使我可以睡得更舒服。(我认为这已经是解决验证问题的错误方法,因此如果您有更好的组织方法,请随时提出建议,而不是对下面的问题进行具体改进。)

到目前为止,我已经找到了这个问题的临时解决方案,如下所示:

module Foo

export some_function

const using_removeable_assertions = true

macro RemoveablyAssert(the_condition)
    if using_removeable_assertions
        return esc(:($the_condition || error("Assertion failed.")))
    else
        return esc("")
    end
end

function some_function(x::Float64,y::Float64)
    #Say this should only be called on positive numbers
    @RemoveablyAssert x>0
    @RemoveablyAssert y>0
    (x + y/2.0)::Float64
end

end

using Foo
这样就行了

julia> some_function(1.0,1.0)
1.5

julia> some_function(1.0,-1.0)
ERROR: Assertion failed.
 in some_function at none:18
如果我重新加载我使用_removeable_assertions=false手动更改了
常量的模块,那么它不仅会跳过这些检查

julia> some_function(1.0,1.0)
1.5

julia> some_function(1.0,-1.0)
0.5
但事实上,正如预期的那样,本机代码与同一个函数完全相同,我甚至从未在其中放过这些行:

julia> @code_native some_function(1.0,1.0)
    .section    __TEXT,__text,regular,pure_instructions
Filename: none
Source line: 19
    pushq   %rbp
    movq    %rsp, %rbp
    movabsq $13174486592, %rax      ## imm = 0x31142B640
Source line: 19
    vmulsd  (%rax), %xmm1, %xmm1
    vaddsd  %xmm0, %xmm1, %xmm0
    popq    %rbp
    ret
例如,如果我定义

function some_function_2(x::Float64,y::Float64)
    (x + y/2.0)::Float64
end
然后

所以:这是溶液的两个理想性质

  • 打开/关闭一大组严格的健全性检查应该像拨动开关一样简单
  • 在“关闭”的情况下,本机代码应该完全没有对检查的任何引用;特别是,不应该有 关闭情况下的性能差异
  • 但我希望解决方案少一点手工操作,多一点惯用或标准

    请注意,手动定义每个函数的两个版本是不切实际的,因为维护它们会变得一团糟。所以我考虑过使用另一个宏,为每个
    一些函数
    生成一个
    一些函数
    ,然后以这种方式手动运行安全检查,但我希望有更好的解决方案,类似于
    julia
    的命令行参数,但特定于该模块。例如,
    使用[safemode=yes]Foo

    与此相关的是,我想知道除了定义一个全局“安全级别”,然后在全局安全级别超过特定检查级别的情况下使用宏有条件地注入检查之外,是否还有处理多个检查“级别”的好方法。如果可以实现上面的
    [safemode=yes]
    思想,那么当然也可以实现,但我想知道是否有更好的方法来组织这些检查


    (FWW,我认为这些检查补充,而不是替代,一个大的测试套件。单独的测试套件不能让我睡懒觉。此外,虽然我的例子是论证验证,我想使用这些检查不仅为前和后的条件,但也适用于各种明智的检查,例如检查方法和WrTI体内的不变量。ng针对我已经犯过的错误进行特定检查并修复,等等)

    我对我的Julia工作做了一些非常类似的事情,我有一个宏,可以完全删除,或者如果编译进来,检查一个掩码,我可以设置它来控制实际检查哪些掩码。 就单元测试而言,我们一直在使用
    FactCheck.jl
    包。 我们计划设置代码来进行代码覆盖率测试(我们不能将我们的内部代码放在GitHub上,因为在GitHub上设置代码很简单),我认为这与单元测试一起,对于确保合理的好代码是至关重要的。
    如果您的代码在GitHub上,我认为从Workalls或codecov.io添加代码覆盖率支持是微不足道的。

    谢谢!我也看过FactCheck,但没有真正领会要点。
    @fact[Computed Value]-->[关于它的谓词]
    @test[关于计算值的谓词]
    相比,什么更好?(尤其是
    @fact 1-->比(2)
    @test 1<2
    …**真的吗??**)我同意分组和上下文是一个加号,但我希望它们最终会成为
    的基础。test
    和其他语法与我的“普遍抵制尽早提交可能被弃用的第三方方法”相悖惯性…,…,但是,我们似乎有类似的方法来考虑测试(和类似的约束)我很想听到更多的re:为什么你发现
    FactCheck
    值得投资。说清楚——我根本不是想说它不值得,也不是想批评写它的人的辛勤工作,只是直截了当地说,到目前为止,我还没有看到曙光re:它是否真的得到了很大的改进,或者仅仅是为了我的用例将是一个问题在没有前期投资成本的情况下,我可以在边缘上稍加修饰。THX当我们开始添加我们自己的单元测试时,我们非常喜欢分组和上下文功能,以及它显示预期值和结果的方式。我们真的觉得没有任何大的前期成本(Emacs中的一些regex查询搜索和替换很快就解决了从
    @test
    @fact
    的变化。如果
    Base.test
    最终具有这些特性,我们可能会后退。我们确实更喜欢处理回归的单元测试包,并让我们对尚未通过的东西进行测试。有趣g、 我再看一下。到目前为止,我的上下文解决方案是无耻地复制@JohnMylesWhite等人在
    DataFrames
    中的每文件报告策略。
    julia> @code_native some_function_2(1.0,1.0)
        .section    __TEXT,__text,regular,pure_instructions
    Filename: none
    Source line: 2
        pushq   %rbp
        movq    %rsp, %rbp
        movabsq $13174493536, %rax      ## imm = 0x31142D160
    Source line: 2
        vmulsd  (%rax), %xmm1, %xmm1
        vaddsd  %xmm0, %xmm1, %xmm0
        popq    %rbp
        ret