From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms8.migadu.com with LMTPS id ODtLKNtBT2U5JgAAauVa8A:P1 (envelope-from ) for ; Sat, 11 Nov 2023 09:56:59 +0100 Received: from aspmx1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id ODtLKNtBT2U5JgAAauVa8A (envelope-from ) for ; Sat, 11 Nov 2023 09:56:59 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 2B33C15711 for ; Sat, 11 Nov 2023 09:56:59 +0100 (CET) Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=SS5GCRKb; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1699693019; a=rsa-sha256; cv=none; b=IdeV/aFheD+4IRXUQ+XJM4YTqhOEhMfG2UYbp3mvFFhPWmom9Rbm7DS2idgSC1spIVVIkJ cJsoVfUh+mRr5ZbXaeyofITci3V6kyWjoxxHL46mGtJywydU9wgL8Zu1ssg/KKwZdCCkYX dwnvkKMOf0RhUfs/7hJlGhxY2FT+ZU7P8RjNboJf0UcQl0jYfjxrcJj1u0QlbQLrV2eFVk ONnKM/sx0QTjP3wJ/eU1sW75GmC/6k/4P/1qeewCau9/0W+ijey+FzfZBf8xSjhXvMdxAf GrP/f6nZoqUY/zedQvk8gjZoiAkKZjQtRJsOa90K5Om4QjjsJbzkWzyII8rYsA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=SS5GCRKb; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1699693019; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=IFu+om3L3v5z5NlmZYSozoLr1Dfdnx5gBziHeQAhY1U=; b=NhLLpzdsynoAefj5sh5ssathwPqMeNCWOht7AdAFVCF3PkP8VAPw3i4Y7nVWCOgUQEp7ZY jyh6M8/eSuYojzVa9GXoycwCY/DV1+uwclZJ8KCKXJoPEfQICItEWV20x2QyXEfhh3pRNk qukY8kwXGmBqokdoK/fmhg2GOETF9MS9Zd+q/OoM44JPAt4VD2cpnS5xNqpSXI1bU77xgu YdOHD2v9+xuOL4Xv9wm/Dd/iowqLn97+9j0rUHsRIXtJ7L426b3NMxQCthK3qTtHgbo3kF +53rRupPWnCTRDDnrFCyERjco+rhehm7adkMfEDD3vJilPMfYk2unA5/hp1YyA== Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r1jmW-0002C0-7s; Sat, 11 Nov 2023 03:55:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r1jmU-0002Bj-KJ for emacs-orgmode@gnu.org; Sat, 11 Nov 2023 03:55:54 -0500 Received: from mail-lf1-x12f.google.com ([2a00:1450:4864:20::12f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1r1jmR-0000f1-Rm for emacs-orgmode@gnu.org; Sat, 11 Nov 2023 03:55:54 -0500 Received: by mail-lf1-x12f.google.com with SMTP id 2adb3069b0e04-507a5f2193bso3110252e87.1 for ; Sat, 11 Nov 2023 00:55:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1699692948; x=1700297748; darn=gnu.org; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=IFu+om3L3v5z5NlmZYSozoLr1Dfdnx5gBziHeQAhY1U=; b=SS5GCRKbkzhR9uCabB5GYy7t2MBp1uPQPHckDERWcClIfoFTO5J8Rk+E+FrEKJAMlo uGwSr+TqUonu8FAwSA25ojsqPOsLV4sZ2+dGnol9o8FtcPYx1Iv6nZXXpg5kVwjzQLOI 8w12JmGorp1KKamkxHnwiEt7lWA4YwvdKrV7Xb9Rvg6HINC72AOlT4lyrYwYh8KzQOJ4 Rb/7bv3uozaLg3UJipldxA3dc90U4JGIJyGTj+nXkp+WRDQ7XYiHx/7BLAOXp4QTMZlk MZhrqLdvy7YJHzkEvf79N08j1/W5xFLIn7NSNOUP7FAqlZb0FX2jYxf42wlqJ14QUqnp ORbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699692948; x=1700297748; h=mime-version:message-id:date:references:in-reply-to:subject:cc:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IFu+om3L3v5z5NlmZYSozoLr1Dfdnx5gBziHeQAhY1U=; b=hD3QuW/FhMRPRhXxltSqPOKfcoEQB5vzHbBE8ulVPLYYQKDPU71xyUPE+lnXbstwTF DOgmqUVJktEydcZOjzhl/tqkCfbr0DRQ1czN2Wyf716OSn9wppPdrZwa64txlfCXtLsv FIvhNjHsFOFSPovcsNXODrNL23mywAMnggUbySnr8gBzL2aLqlz6DmIRzI6ZKwJ3wo7m 3mszTUF2iZnB/EXAJ1vT6jvoh0PDBNhLZuEkye1kksiSmsOK7A8Vc+BZjsRkF8OE3Jau XSmVutCkjFr4Ed6YMzcLAnwVKDYcy2DsQgicDmlk9xnG2u6y8OYA+SeAG6U2ADHxwXg/ oW5g== X-Gm-Message-State: AOJu0YxILH87Xc5j9XCBSHT/t0fEEHr6eOzH5N/Ruwk71J3Cn1h1Ls95 q4HrNOgi7Lb00qO7EDQoBJTtkUClMcwuGw== X-Google-Smtp-Source: AGHT+IEjL8aVR9Y/j2erPQmo8sYUsQrT8zpj6ufELrVnfQlG32wjg1HYKKb1Z5uQ7AkSal97z85jxw== X-Received: by 2002:a19:6904:0:b0:4fe:4896:b6ab with SMTP id e4-20020a196904000000b004fe4896b6abmr453289lfc.15.1699692947729; Sat, 11 Nov 2023 00:55:47 -0800 (PST) Received: from sonyvaio ([217.71.131.234]) by smtp.gmail.com with ESMTPSA id h33-20020a0565123ca100b005056c997ed6sm208407lfv.163.2023.11.11.00.55.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Nov 2023 00:55:44 -0800 (PST) From: Ilya Chernyshov To: Ihor Radchenko Cc: emacs-orgmode Subject: Re: [PATCH] testing: Delete duplicate tests In-Reply-To: <878r78ftvs.fsf@localhost> References: <87cz0xndem.fsf@gmail.com> <87cz0wyw9m.fsf@localhost> <87y1ilitzo.fsf@localhost> <87fs3zybvj.fsf@gmail.com> <875y4viv14.fsf@localhost> <878r78ftvs.fsf@localhost> Date: Sat, 11 Nov 2023 15:55:37 +0700 Message-ID: <87sf5cr7na.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::12f; envelope-from=ichernyshovvv@gmail.com; helo=mail-lf1-x12f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Queue-Id: 2B33C15711 X-Migadu-Scanner: mx12.migadu.com X-Migadu-Spam-Score: -9.41 X-Spam-Score: -9.41 X-TUID: L/kCALUsAFst --=-=-= Content-Type: text/plain Ihor Radchenko writes: > I saw you using your function to detect the existing duplicate tests. > However, it would also be nice to add it as a test of its own to detect > duplicates in future. WDYT? Sure, here it is. In the patch, I added a new file (testing/lisp/test-deduplicator.el) with a test that checks for duplicate forms (not just should, should-not, should-error macros) in all test files. Changes in other files serve as an example of how to use `org-test-ignore-duplicate' to make sure that the test deduplicator skips certain duplicate forms. There's a lot of tests to change before merging. I'll handle them and submit a new patch if you have no questions about the code. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-testing-Add-testing-lisp-test-deduplicator.el.patch >From 3b38450f7de8bd168d8795728454d9f4db720843 Mon Sep 17 00:00:00 2001 From: Ilya Chernyshov Date: Tue, 5 Sep 2023 22:40:59 +0700 Subject: [PATCH] testing: Add testing/lisp/test-deduplicator.el * testing/lisp/test-deduplicator.el: Add test unit that checks for duplicate forms in ert tests. * testing/lisp/test-ob-lob.el (test-ob-lob/caching-call-line, test-ob-lob/named-caching-call-line, test-ob/just-one-results-block): Ignore duplicate forms via `org-test-ignore-duplicate' * testing/lisp/test-ob.el (test-ob/just-one-results-block): Ignore duplicate forms via `org-test-ignore-duplicate' * testing/lisp/test-org.el (test-org/goto-sibling, test-org/backward-element, test-org/up-element): Ignore duplicate forms via `org-test-ignore-duplicate' --- testing/lisp/test-deduplicator.el | 224 ++++++++++++++++++++++++++++++ testing/lisp/test-ob-lob.el | 10 +- testing/lisp/test-ob.el | 3 +- testing/lisp/test-org.el | 81 ++++++----- 4 files changed, 275 insertions(+), 43 deletions(-) create mode 100644 testing/lisp/test-deduplicator.el diff --git a/testing/lisp/test-deduplicator.el b/testing/lisp/test-deduplicator.el new file mode 100644 index 000000000..28b5d66f0 --- /dev/null +++ b/testing/lisp/test-deduplicator.el @@ -0,0 +1,224 @@ +;;; test-deduplicator.el --- Tests for finding duplicates in Org tests -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Ilya Chernyshov +;; Authors: Ilya Chernyshov + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: + +;; Unit tests that check for duplicate forms (including `should', +;; `should-not', `should-error') in all Org test files. Forms are +;; considered duplicate if they are `equal-including-properties' and +;; nested at the same level. To ignore a form or a group of forms, +;; wrap them in `org-test-ignore-duplicate'. + +;;; Code: + +(require 'org-test "../testing/org-test") + +(defvar test-deduplicator-files + (directory-files (expand-file-name "lisp" org-test-dir) t "\\.el$")) + +(defvar test-deduplicator-duplicate-forms nil + "A nested list of the form: + + (((file test-name [(form-1 . numerical-order) + (form-2 . numerical-order) ...]) + (dup-form-1 . (numerical-order [numerical-order ...])) + [ (dup-form-2 . (numerical-order [numerical-order ...])) + (dup-form-3 . (numerical-order [numerical-order ...])) + ...]) + + ((file test-name [(form-1 . numerical-order) + (form-2 . numerical-order) ...]) + (dup-form-1 . (numerical-order [numerical-order ...])) + [ (dup-form-2 . (numerical-order [numerical-order ...])) + (dup-form-3 . (numerical-order [numerical-order ...])) + ...]) + + ... + ) + +Where + + (file test-name [(form-1 . numerical-order) + (form-2 . numerical-order) ...]) + +is a path to duplicates. For example, the path for the +duplicates in the following test: + + test-ob-haskell-ghci.el + + (ertdeftest ob-haskell/session-named-none-means-one-shot-sessions () + \"When no session, use a new session. + \"none\" is a special name that means `no session'.\" + (let ((var-1 \"value\")) + (when var-1 + (should-not (equal 2 (test-ob-haskell-ghci \":session \"none\"\" \"x\" nil))) + (test-ob-haskell-ghci \":session none\" \"x=2\") + (should-not (equal 2 (test-ob-haskell-ghci \":session \"none\"\" \"x\" nil))) + (test-ob-haskell-ghci \":session none\" \"x=2\")))) + +would look like this: + + (\"test-ob-haskell-ghci.el\" + ob-haskell/session-named-none-means-one-shot-sessions + (let . 4) (when . 2)) + +And the records about the duplicates would look like this: + + ((test-ob-haskell-ghci \":session none\" \"x=2\") 5 3) + ((should-not (equal 2 (test-ob-haskell-ghci \":session \"none\"\" \"x\" nil))) 4 2)") + +(defvar test-deduplicator-forms nil + "Nested alist of found forms and paths to them (not filtered).") + +(defmacro org-test-ignore-duplicate (&rest body) + "Eval BODY forms sequentially and return value of last one. + +The macro's body will be ignored by +`test-deduplicator/detect-duplicate-tests' test to ignore +duplicate forms inside the body." + (declare (indent 0)) + `(progn ,@body)) + +(ert-deftest test-org-tests/detect-duplicate-tests () + "Try to find duplicate forms." + + (should-not (test-deduplicator-find-duplicates test-deduplicator-files))) + +(defun test-deduplicator-find-duplicates (files) + "Try to find duplicate forms in FILES. + +If duplicates are found, record them into +`test-deduplicator-duplicate-forms', `message' paths to them in a +human-readable format and return the value. + +Forms are considered duplicate if they are nested at the same +level." + (setq test-deduplicator-forms nil) + (dolist (file files) + (with-current-buffer (find-file-noselect file) + (save-excursion + (goto-char (point-min)) + (while (search-forward "(ert-deftest" nil t) + (goto-char (match-beginning 0)) + (ignore-errors + (while-let ((form (or (read (current-buffer)) t))) + (test-deduplicator-search-forms-recursively + form (list file (cadr form))))))))) + (setq test-deduplicator-duplicate-forms + (seq-filter + #'cdr (mapcar + (lambda (file) + (cons + (car file) + (seq-filter #'caddr (cdr file)))) + test-deduplicator-forms))) + (when test-deduplicator-duplicate-forms + (let ((res (concat "Found duplicates (To ignore duplicate forms,\n" + "wrap them in `org-test-ignore-duplicate'):\n"))) + (dolist (path test-deduplicator-duplicate-forms) + (let* ((file (file-relative-name (caar path))) + (test-name (symbol-name (cadar path))) + (path-inside-test (cddar path)) + (result "") + (string-path (append (list file test-name) + (mapcar (lambda (x) + (symbol-name (car x))) + path-inside-test))) + (iter 0) + (print-level 3)) + (dolist (x string-path) + (cl-callf concat result + (format "%s%s\n" (make-string (* iter 2) ? ) x)) + (cl-incf iter)) + (cl-callf concat result + (mapconcat + (lambda (x) (format "%s%S: %d times\n" + (make-string (* iter 2) ? ) + (car x) + (length (cdr x)))) + (cdr path))) + (cl-callf concat res result))) + (message "%s" res))) + test-deduplicator-duplicate-forms) + +(defun test-deduplicator-search-forms-recursively (form form-path) + "Search for forms recursively in FORM. + +FORM-PATH is list of the form: + (\"file-path\" ert-test-symbol + (symbol-1 . sexp-order-1) (symbol-2 . sexp-order-2)) + +Write each form to `test-deduplicator-forms'" + (dotimes (iter (length form)) + (pcase (car-safe (nth iter form)) + ((or `skip-unless `org-test-ignore-duplicate)) + ((pred (not null)) + (push iter (alist-get (nth iter form) + (alist-get form-path test-deduplicator-forms + nil nil #'equal) + nil nil #'equal-including-properties)) + (unless (member (car-safe (nth iter form)) + '(should-not should should-error)) + (test-deduplicator-search-forms-recursively + (nth iter form) + (append form-path (list (cons (car (nth iter form)) iter))))))))) + +;;; Tests + +(defvar test-deduplicator-file-path + (expand-file-name "test-deduplicator.el" + (expand-file-name "lisp" org-test-dir))) + +(ert-deftest test-org-tests/testing-test-deduplicator () + "" + (should + (equal + (test-deduplicator-find-duplicates + (list test-deduplicator-file-path)) + `(((,(expand-file-name "lisp/test-deduplicator.el" org-test-dir) + test-org-tests/test-with-nested-duplicates) + ((format "%s" "string") 7 5) + ((let ((var "string")) (should (message "123 %s" var))) 6 4)) + (((expand-file-name "lisp/test-deduplicator.el" org-test-dir) + test-org-tests/test-with-duplicates-at-root) + ((should (message "123")) 6 4)))))) + +;;; Tests with duplicate forms to check the deduplicator + +(ert-deftest test-org-tests/test-with-duplicates-at-root () + "Test with duplicates at the root." + (should (message "123")) + (format "%s" "string") + (should + (message "123"))) + +(ert-deftest test-org-tests/test-with-nested-duplicates () + "Test with nested duplicates." + (let ((var "string")) + (should + (message "123 %s" var))) + (format "%s" "string") + (let ((var "string")) + (should (message "123 %s" var))) + (format "%s" "string")) + +(provide 'test-deduplicator) + +;;; test-deduplicator.el ends here diff --git a/testing/lisp/test-ob-lob.el b/testing/lisp/test-ob-lob.el index 188fee4c0..66dfd0eab 100644 --- a/testing/lisp/test-ob-lob.el +++ b/testing/lisp/test-ob-lob.el @@ -152,8 +152,9 @@ for export (should (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1)) ;; if cached, second evaluation will retain the t value - (should - (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1))))) + (org-test-ignore-duplicate + (should + (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1)))))) (ert-deftest test-ob-lob/named-caching-call-line () (let ((temporary-value-for-test 0)) @@ -170,8 +171,9 @@ for export (should (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1)) ;; if cached, second evaluation will retain the t value - (should - (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1))))) + (org-test-ignore-duplicate + (should + (eq (org-babel-execute-src-block nil (org-babel-lob-get-info)) 1)))))) (ert-deftest test-ob-lob/assignment-with-newline () "Test call lines with an argument containing a newline character." diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index 42c77ca56..0153de889 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -645,7 +645,8 @@ duplicate results block." (org-babel-execute-src-block) (org-babel-execute-src-block) ; second code block execution (should (search-forward "Hello")) ; the string inside the source code block - (should (search-forward "Hello")) ; the same string in the results block + (org-test-ignore-duplicate + (should (search-forward "Hello"))) ; the same string in the results block (should-error (search-forward "Hello")))) (ert-deftest test-ob/nested-code-block () diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 612bfa1e5..4e23488be 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -2490,7 +2490,8 @@ Text. (should-not (org-goto-sibling)) (should (org-goto-sibling 'previous)) (should (looking-at-p "^\\*\\* Heading 2")) - (should (org-goto-sibling 'previous)) + (org-test-ignore-duplicate + (should (org-goto-sibling 'previous))) (should (looking-at-p "^\\*\\* Heading 1")) (should-not (org-goto-sibling 'previous))) ;; Inside heading. @@ -2533,7 +2534,8 @@ test (should-not (org-goto-sibling)) (should (org-goto-sibling 'previous)) (should (looking-at-p "^\\*\\* Heading 2")) - (should (org-goto-sibling 'previous)) + (org-test-ignore-duplicate + (should (org-goto-sibling 'previous))) (should (looking-at-p "^\\*\\* Heading 1")) (should-not (org-goto-sibling 'previous))))) @@ -5223,27 +5225,28 @@ Outside." ;; 7.1. At beginning of sub-list: expected to move to the ;; paragraph before it. (goto-line 4) - (org-backward-element) - (should (looking-at "item1")) - ;; 7.2. At an item in a list: expected to move at previous item. - (goto-line 8) - (org-backward-element) - (should (looking-at " - sub2")) - (goto-line 12) - (org-backward-element) - (should (looking-at "- item1")) - ;; 7.3. At end of list/sub-list: expected to move to list/sub-list - ;; beginning. - (goto-line 10) - (org-backward-element) - (should (looking-at " - sub1")) - (goto-line 15) - (org-backward-element) - (should (looking-at "- item1")) - ;; 7.4. At blank-lines before list end: expected to move to top - ;; item. - (goto-line 14) - (org-backward-element) + (org-test-ignore-duplicate + (org-backward-element) + (should (looking-at "item1")) + ;; 7.2. At an item in a list: expected to move at previous item. + (goto-line 8) + (org-backward-element) + (should (looking-at " - sub2")) + (goto-line 12) + (org-backward-element) + (should (looking-at "- item1")) + ;; 7.3. At end of list/sub-list: expected to move to list/sub-list + ;; beginning. + (goto-line 10) + (org-backward-element) + (should (looking-at " - sub1")) + (goto-line 15) + (org-backward-element) + (should (looking-at "- item1")) + ;; 7.4. At blank-lines before list end: expected to move to top + ;; item. + (goto-line 14) + (org-backward-element)) (should (looking-at "- item1")))) (ert-deftest test-org/up-element () @@ -5281,21 +5284,23 @@ Outside." - item2" ;; 4.1. Within an item: move to the item beginning. (goto-line 8) - (org-up-element) - (should (looking-at " - sub2")) - ;; 4.2. At an item in a sub-list: move to parent item. - (goto-line 4) - (org-up-element) - (should (looking-at "- item1")) - ;; 4.3. At an item in top list: move to beginning of whole list. - (goto-line 10) - (org-up-element) - (should (looking-at "- item1")) - ;; 4.4. Special case. At very top point: should move to parent of - ;; list. - (goto-line 2) - (org-up-element) - (should (looking-at "\\* Top")))) + (org-test-ignore-duplicate + (org-up-element) + (should (looking-at " - sub2")) + ;; 4.2. At an item in a sub-list: move to parent item. + (goto-line 4) + (org-up-element) + (should (looking-at "- item1")) + ;; 4.3. At an item in top list: move to beginning of whole list. + (goto-line 10) + (org-up-element) + (org-test-ignore-duplicate + (should (looking-at "- item1"))) + ;; 4.4. Special case. At very top point: should move to parent of + ;; list. + (goto-line 2) + (org-up-element) + (should (looking-at "\\* Top"))))) (ert-deftest test-org/down-element () "Test `org-down-element' specifications." -- 2.41.0 --=-=-=--