首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是Clojure中的生成测试?

什么是Clojure中的生成测试?
EN

Stack Overflow用户
提问于 2017-04-11 14:14:19
回答 2查看 1.8K关注 0票数 6

我偶然发现了Generative Testing in Clojure with spec的概念,并想了解它。

此外,提供一些例子将是非常有用的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-11 15:04:15

作为介绍性阅读,我们已经获得了基本原理和概述指南,它应该为您提供关于为什么和如何的信息。

如果您想要一个比较复杂的例子,我们可以以string->semantic-version函数leiningen.release为例

代码语言:javascript
复制
(defn string->semantic-version [version-string]
  "Create map representing the given version string. Returns nil if the
  string does not follow guidelines setforth by Semantic Versioning 2.0.0,
  http://semver.org/"
  ;; <MajorVersion>.<MinorVersion>.<PatchVersion>[-<Qualifier>][-SNAPSHOT]
  (if-let [[_ major minor patch qualifier snapshot]
           (re-matches
            #"(\d+)\.(\d+)\.(\d+)(?:-(?!SNAPSHOT)([^\-]+))?(?:-(SNAPSHOT))?"
            version-string)]
    (->> [major minor patch]
         (map #(Integer/parseInt %))
         (zipmap [:major :minor :patch])
         (merge {:qualifier qualifier
                 :snapshot snapshot}))))

它接受一个字符串,并尝试将其解析为一个程序可读的映射,表示某个工件的版本号。它的规范可能看起来如下:

首先,一些依赖关系

代码语言:javascript
复制
(ns leiningen.core.spec.util
  (:require
   [clojure.spec           :as spec]
   [clojure.spec.gen       :as gen]
   [miner.strgen           :as strgen]
   [clojure.spec.test      :as test]
   [leiningen.release      :as release]))

然后是助手宏。

代码语言:javascript
复制
(defmacro stregex
  "Defines a spec which matches a string based on a given string
  regular expression. This the classical type of regex as in the
  clojure regex literal #\"\""
  [string-regex]
  `(spec/with-gen
     (spec/and string? #(re-matches ~string-regex %))
     #(strgen/string-generator ~string-regex)))

然后是语义版本的定义。

代码语言:javascript
复制
(spec/def ::semantic-version-string
  (stregex #"(\d+)\.(\d+)\.(\d+)(-\w+)?(-SNAPSHOT)?"))

还有一些帮手规范

代码语言:javascript
复制
(spec/def ::non-blank-string
  (spec/and string? #(not (str/blank? %))))
(spec/def ::natural-number
  (spec/int-in 0 Integer/MAX_VALUE))

用于定义生成的映射中的键。

代码语言:javascript
复制
(spec/def ::release/major     ::natural-number)
(spec/def ::release/minor     ::natural-number)
(spec/def ::release/patch     ::natural-number)
(spec/def ::release/qualifier ::non-blank-string)
(spec/def ::release/snapshot  #{"SNAPSHOT"})

和地图本身

代码语言:javascript
复制
(spec/def ::release/semantic-version-map
  (spec/keys :req-un [::release/major ::release/minor ::release/patch
                      ::release/qualifier ::release/snapshot]))

后面跟着函数规范:

代码语言:javascript
复制
(spec/fdef release/string->semantic-version
           :args (spec/cat :version-str ::release/semantic-version-string)
           :ret  ::release/semantic-version-map)

现在,我们可以让Clojure Spec生成测试数据并将其输入函数本身,以测试它是否满足我们为其提供的约束:

代码语言:javascript
复制
(test/check `release/version-map->string)
=> ({:spec #object[clojure.spec$fspec_impl$reify__14248 0x16c2555 "clojure.spec$fspec_impl$reify__14248@16c2555"],
     :clojure.spec.test.check/ret {:result true,
                                   :num-tests 1000,
                                   :seed 1491922864713},
     :sym leiningen.release/version-map->string})

这告诉我们,在为我们生成的1000个测试用例规范中,每个函数都通过了。

票数 15
EN

Stack Overflow用户

发布于 2017-04-11 15:57:58

在深入研究clojure/test.check之前,您可能会发现最容易开始查看Clojure Spec从项目页面:

代码语言:javascript
复制
(require '[clojure.test.check :as tc])
(require '[clojure.test.check.generators :as gen])
(require '[clojure.test.check.properties :as prop])

(def sort-idempotent-prop
  (prop/for-all [v (gen/vector gen/int)]
    (= (sort v) (sort (sort v)))))

(tc/quick-check 100 sort-idempotent-prop)
;; => {:result true, :num-tests 100, :seed 1382488326530}

在散文中,这个测试的内容是:对于整数的所有向量,v,排序v等于对v排序两次。 如果我们的测试失败了怎么办?test.check将尝试找到仍然失败的“较小”输入。这个过程叫做收缩。让我们看看它的作用:

代码语言:javascript
复制
(def prop-sorted-first-less-than-last
  (prop/for-all [v (gen/not-empty (gen/vector gen/int))]
    (let [s (sort v)]
      (< (first s) (last s)))))

(tc/quick-check 100 prop-sorted-first-less-than-last)
;; => {:result false, :failing-size 0, :num-tests 1, :fail [[3]],
       :shrunk {:total-nodes-visited 5, :depth 2, :result false,
                :smallest [[0]]}}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43348511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档