برنامه نویسی

Tsonnet #2 – تست های CRAM به نجات

در پست قبلی ، من تجزیه و تحلیل Literals JSON را به Tsonnet اضافه کردم:

چیز مهمی وجود دارد که هنوز از دست رفته است و این آزمایش است. بهتر است بدون تضمین مشخصات زبان با تست های خودکار تأیید نشود.

بیایید این کار را انجام دهیم!

اضافه کردن کتابخانه های آزمایش

ما برای نوشتن تست های خودکار Alcotest اضافه خواهیم کرد – به نظر می رسد امروزه به جای ONIT ، کتابخانه آزمایش مورد علاقه برای برنامه نویسان OCAML است. بیایید BISECT_PPX را برای گزارش پوشش اضافه کنیم:

diff --git a/dune-project b/dune-project
index cf8c03f..383bbef 100644
--- a/dune-project
+++ b/dune-project
@@ -25,7 +25,15 @@
   (dune
    (>= 3.16.0))
   (menhir
-   (= 20240715)))
+   (= 20240715))
+  (alcotest
+   (and
+    :with-test
+    (>= 1.8.0)))
+  (bisect_ppx
+   (and
+    :with-test
+    (>= 2.8.3))))
  (tags
   (jsonnet interpreter compiler)))
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در تپه ، می توانیم مشخص کنیم که وابستگی به یک محیط خاص تعلق دارد – در این حالت ، تست محیط به این ترتیب ، ما وابستگی های آزمایش را به باینری های رهاسازی حمل نمی کنیم.

دویدن dune runtest راحت است ، اما فرمان پوشش نیست. بیایید یک Makefile اضافه کنیم تا ذهن خود را از جزئیات آزاد کنیم:

diff --git a/.gitignore b/.gitignore
index 69fa449..39136cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 _build/
+_coverage/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..688c42d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+default: test
+
+.PHONY: test
+test:
+       dune runtest
+
+.PHONY: coverage
+coverage:
+       dune runtest --instrument-with bisect_ppx --force
+       bisect-ppx-report html
+
+.PHONY: clean
+clean:
+       dune clean
+       rm -rf _coverage/
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

من قدردانی می کنم که به سادگی دویدن make هدف make testبشر من همیشه دوست دارم دستور آزمون را به عنوان پیش فرض برای پروژه هایم داشته باشم. در make coverage اکنون فرمان برای اجرای محلی راحت است و می توانیم هنگام تنظیم کار CI بعداً از آن استفاده کنیم.

حال ، بیایید Dune را پیکربندی کنیم.

کمی پیکربندی

diff --git a/bin/dune b/bin/dune
index 300e220..b274fc4 100644
--- a/bin/dune
+++ b/bin/dune
@@ -2,3 +2,8 @@
  (public_name tsonnet)
  (name main)
  (libraries tsonnet))
+
+(cram
+ (deps
+  %{bin:tsonnet}
+  (source_tree ../samples)))
diff --git a/test/cram/dune b/test/cram/dune
new file mode 100644
index 0000000..4c224ef
--- /dev/null
+++ b/test/cram/dune
@@ -0,0 +1,4 @@
+(cram
+ (deps
+  %{bin:tsonnet}
+  (source_tree ../../samples)))
diff --git a/test/dune b/test/dune
index f8dbe1e..bd42c05 100644
--- a/test/dune
+++ b/test/dune
@@ -1,2 +1,5 @@
 (test
- (name test_tsonnet))
+ (name test_tsonnet)
+ (libraries tsonnet alcotest)
+ (deps
+  (source_tree ../samples)))
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ما قصد داریم مشخص کنیم که می توانیم تست های CRAM را در آن بنویسیم bin دایرکتوری و تست ها دو وابستگی دارند:

  1. باینری Tsonnet که Dune برای ما کامپایل خواهد کرد
  2. در samples دایرکتوری ، جایی که ما نمونه های فایل JSONNET را ذخیره می کنیم ، به عنوان ورودی در آزمایشات استفاده می شود

ما همچنین در حال اضافه کردن یک پیکربندی مشابه به test دایرکتوری ، جایی که ما مشخص می کنیم که تست های CRAM در test/cram پوشه و وابستگی پرونده های باینری و نمونه.

سطح ورودی اصلی test پوشه پرونده های نمونه را به عنوان وابستگی و سرنوشت کتابخانه

در بخش بعدی به جزئیات بیشتری در مورد تست های CRAM می پردازم.

برای پوشش:

diff --git a/lib/dune b/lib/dune
index 9660313..3452131 100644
--- a/lib/dune
+++ b/lib/dune
@@ -1,5 +1,7 @@
 (library
- (name tsonnet))
+ (name tsonnet)
+ (instrumentation
+  (backend bisect_ppx)))

 (menhir
  (modules parser))
diff --git a/lib/lexer.mll b/lib/lexer.mll
index a581fcd..585673b 100644
--- a/lib/lexer.mll
+++ b/lib/lexer.mll
@@ -1,4 +1,5 @@
 {
+  [@@@coverage exclude_file]
   open Lexing
   open Parser
   exception SyntaxError of string
diff --git a/lib/parser.mly b/lib/parser.mly
index 6872459..2396dfe 100644
--- a/lib/parser.mly
+++ b/lib/parser.mly
@@ -1,3 +1,7 @@
+%{
+  [@@@coverage exclude_file]
+%}
+
 %token  INT
 %token  FLOAT
 %token NULL
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ما نیاز به ساز داریم bisect_ppx ابزار پوشش برای تنظیم lib دایرکتوری به عنوان هدف خود ، در غیر این صورت ، این دایرکتوری را کاملاً نادیده می گیرد ، جایی که تمام منطق کامپایلر ما در آن زندگی می کند.

از آنجا که Lexer و Parser تولید می شوند ، هیچ نکته ای برای بررسی پوشش برای آنها وجود ندارد ، بنابراین ما اساساً حاشیه نویسی می کنیم که آنها را از این امر مستثنی کنیم.

اکنون ما آماده هستیم تا سرانجام برخی از تست ها را بنویسیم.

آزمایش با تست های CRAM

آیا می دانید تست های CRAM چیست؟

TLDR ، آزمون های CRAM تست های ادغام هستند که یک جلسه پوسته را توصیف می کنند. آنها برای آزمایش برنامه های CLI شگفت انگیز هستند!

آیا می دانید چه چیز دیگری جالب است؟ Dune پشتیبانی داخلی برای نوشتن تست های CRAM دارد. دلیل اضافه شدن هیچ کتابخانه جدیدی برای رسیدگی به آن.

ما می توانیم مستندات قابل اجرا را با آن بنویسیم. به یاد داشته باشید که ما Dune را تنظیم کردیم تا تست های CRAM را در آن انجام دهیم bin پوشه؟ در اینجا تست های CRAM برای پوشش برخی موارد استفاده از TSONNET آورده شده است:

diff --git a/bin/usage.t b/bin/usage.t
new file mode 100644
index 0000000..7d13b46
--- /dev/null
+++ b/bin/usage.t
@@ -0,0 +1,10 @@
+Using the Tsonnet program:
+
+  $ tsonnet ../samples/literals/int.jsonnet
+  42
+
+  $ tsonnet ../samples/literals/string.jsonnet
+  "Hello, world!"
+
+  $ tsonnet ../samples/literals/object.jsonnet
+  {"int_attr": 1, "float_attr": 4.200000, "string_attr": "Hello, world!", "null_attr": null, "array_attr": [1, false, {}], "obj_attr": {"a": true, "b": false, "c": {"d": [42]}}}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

پرونده های تست CRAM شما نیاز به داشتن .t پسوند

می توانید متن رایگان را با دستورات پوسته به درستی مخلوط کنید. خط درست زیر دستور خروجی مورد انتظار است.

چقدر جالب است؟!

در test/cram دایرکتوری می توانیم هر پرونده منبع نمونه را به همراه خروجی مورد انتظار آن آزمایش کنیم:

diff --git a/test/cram/literals.t b/test/cram/literals.t
new file mode 100644
index 0000000..c7b1c2a
--- /dev/null
+++ b/test/cram/literals.t
@@ -0,0 +1,36 @@
+  $ tsonnet ../../samples/literals/int.jsonnet
+  42
+
+  $ tsonnet ../../samples/literals/float.jsonnet
+  4.222222222222222
+
+  $ tsonnet ../../samples/literals/negative_int.jsonnet
+  -42
+
+  $ tsonnet ../../samples/literals/negative_float.jsonnet
+  -4.222222222222222
+
+  $ tsonnet ../../samples/literals/true.jsonnet
+  true
+
+  $ tsonnet ../../samples/literals/false.jsonnet
+  false
+
+  $ tsonnet ../../samples/literals/null.jsonnet
+  null
+
+  $ tsonnet ../../samples/literals/string.jsonnet
+  "Hello, world!"
+
+  $ tsonnet ../../samples/literals/array.jsonnet
+  [ 1, 2.0, "hi", null ]
+
+  $ tsonnet ../../samples/literals/object.jsonnet
+  {
+    "int_attr": 1,
+    "float_attr": 4.2,
+    "string_attr": "Hello, world!",
+    "null_attr": null,
+    "array_attr": [ 1, false, {} ],
+    "obj_attr": { "a": true, "b": false, "c": { "d": [ 42 ] } }
+  }
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای نهایی کردن ، بیایید آزمون ها را اجرا کنیم:

$ dune runtest
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

با گذشت همه آزمایشات ، هیچ خطایی وجود ندارد.

بیایید یک خطای کوچک را معرفی کنیم ، مقدار خروجی یک یا دو آزمایش را تغییر دهیم و ببینیم که چگونه ارائه می شود:

در اینجا تغییرات خطای معرفی شده ما به طور عمدی آورده شده است:

diff --git a/test/cram/literals.t b/test/cram/literals.t
index c7b1c2a..54d455f 100644
--- a/test/cram/literals.t
+++ b/test/cram/literals.t
@@ -1,8 +1,8 @@
   $ tsonnet ../../samples/literals/int.jsonnet
-  42
+  666

   $ tsonnet ../../samples/literals/float.jsonnet
-  4.222222222222222
+  4.23

   $ tsonnet ../../samples/literals/negative_int.jsonnet
   -42
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

خروجی تست ها:

$ dune runtest
File "test/cram/literals.t", line 1, characters 0-0:
diff --git a/_build/.sandbox/0a16dd95b0ff6ebafcf09f03744c5c4c/default/test/cram/literals.t b/_build/.sandbox/0a16dd95b0ff6ebafcf09f03744c5c4c/default/test/cram/literals.t.corrected
index 54d455f..c7b1c2a 100644
--- a/_build/.sandbox/0a16dd95b0ff6ebafcf09f03744c5c4c/default/test/cram/literals.t
+++ b/_build/.sandbox/0a16dd95b0ff6ebafcf09f03744c5c4c/default/test/cram/literals.t.corrected
@@ -1,8 +1,8 @@
   $ tsonnet ../../samples/literals/int.jsonnet
-  666
+  42

   $ tsonnet ../../samples/literals/float.jsonnet
-  4.23
+  4.222222222222222

   $ tsonnet ../../samples/literals/negative_int.jsonnet
   -42
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

مشاهده مقدار مورد انتظار و نتیجه واقعی که به دست آوردیم بسیار آسان است. خوب نیست؟!

پایان

تست های CRAM به یکی از ابزارهای مورد علاقه من تبدیل شده است. اگر من یک برنامه CLI را جدی می نویسم بدون آنها زندگی نمی کنم.

این ایده جدیدی نیست. اولین باری که دیدم چیزی مشابه در اکسیر از طریق Doctests بود. من در جایی خوانده ام که این بسته Cram Python جایی است که سرچشمه آن است ، اما مطمئناً نمی توانم بگویم. آخرین باری که سالها پیش امتحان کردم ، اما تا آنجا که می دانم ، Rust دارای آزمایشات مستندات است.

من نمی دانم چه کسی را کپی کرده است ، اما امیدوارم این روند ادامه یابد. این یک ویژگی بسیار جالب است که امیدوارم هر زبان برنامه نویسی ، یا به طور کامل به عنوان تست های CRAM یا جزئی به عنوان تست های مستندات ، پیاده سازی کند.

سلب مسئولیت: سرنوشت در حال حاضر در حال حاضر بیکار نشسته است ، زیرا علاوه بر تست های CRAM ، هیچ تست واحد یا تست ادغام وجود ندارد. سرانجام ، وجود خواهد داشت. من فقط پیش بینی کردم که وابستگی را بلافاصله اضافه کنم.

نظر شما در مورد تست های CRAM چیست؟


با تشکر از شما برای خواندن بیت شاید عاقلانه! برای دریافت پست های جدید در مورد تست های TSONNET و CRAM مشترک شوید.

pho توسط تای بوی در غیر قابل پرواز

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا