歡迎您光臨本站 註冊首頁

用 Emacs Muse 來製作測試結果報告

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
Emacs Muse 是一個可以在 Emacs 中寫 Wiki 文檔的插件,通過 Emacs Muse,我們可以很容易地編寫 Wiki 文檔,並生成各種格式的文件。本文介紹了如何擴展使用 Emacs Muse —— 一個 Emacs 編輯器插件來生成精美的測試結果報告。

前言

Emacs 是一個開放源代碼的編輯器。由於它使用效率高,可擴展性強,自20世紀70年代誕生以來就一直經久不衰,受到廣大開發人員的熱烈追捧。關於 Emacs 的各種介紹和使用技巧教程屢見不鮮。而本文所介紹的 Emacs Muse 是 Emacs 的一個擴展插件,它的前身就是 Emacs Wiki。由於 Emacs Wiki Mode 原作者 Michael Olson 需要重新架構代碼,才另外創立了一個新的 Emacs Muse 項目。通過該插件,我們可以在 Emacs 中寫 Wiki 文檔,生成各種格式,包括網頁,pdf ,DocBook ,LaTex 等等,並可以直接發布到網路中。

我們在工作過程中,往往需要製作一些結果報告,例如測試結果報告。在一份測試報告中,需要統計測試結果,並對結果進行一定的分析和總結。如果我們想製作一份精美的報告,包括能對不同的結果著色,自動統計結果,對結果分析能有按照不同的格式來突出顯示,這樣的工作完全可以通過 Emacs Muse 來實現。而且 Emacs Muse 可能按照 Wiki 網頁的要求來生成 HTML 格式的網頁,發布到網路中供人瀏覽。





Emacs Muse 的安裝與配置

從 Emacs Muse 的官方網站上(參考資源)可以下載最新的 Muse 安裝包,解壓后修改Makefile.defs 文件來設置 Emacs 的安裝路徑,如清單1所示,該路徑是 Mac OS X 平台下 Emacs 的設置,其他平台也可以類似修改。


清單 1 Makefile.defs示例
                  #設置EMACS的路徑  EMACS    = emacs  SITEFLAG = --no-site-file  #設置Muse安裝路徑  DESTDIR  =  PREFIX   = /Applications/Emacs.app/Contents/Resources  ELISPDIR = $(DESTDIR)$(PREFIX)/site-lisp/muse  INFODIR  = $(DESTDIR)$(PREFIX)/info  

安裝路徑設置完成後,用 GNU Make 編譯安裝 Muse ,只需要運行 make install 命令即可。

安裝完成後,我們需要修改 Emacs 的配置文件 .emacs 來載入 Muse 包,添加如清單2所示的代碼到 .Emacs 文件中。


清單2 .emacs文件配置
                  (require 'muse-mode)    (require 'muse-html)         ;添加html格式的支持  (require 'muse-latex)        ; 添加latex格式的支持  (require 'muse-texinfo)      ; 添加texinfo格式的支持  (require 'muse-docbook)      ; 添加docbook格式的支持  (require 'muse-wiki nil t)     (require 'muse-project)      ; 添加wiki project的支持    ;設置編碼方式為utf-8  (setq muse-html-meta-content-type (concat "text/html; charset=utf-8"))    ;新建一個wiki工程  (setq muse-project-alist        '(("MyWiki"           ("~/Documents/wiki" :default "index")           (:base "html" :path "~/Document/wiki/publish"))))  

這樣就完成了配置,在這個配置文件里創建了我們第一個 wiki 工程 MyWiki。





Emacs Muse的基本操作

配置完成以後重新啟動 Emacs,就已經載入了 Muse。這時所有的以 muse 為擴展名的文件都是 Emacs Muse 的源文件,我們只需要用一些簡單的標記來編寫 muse 文件,然後用 Emacs 來生成各種格式的輸出,下面我們就以生成一個簡單的 Wiki 網頁為例介紹下 Emacs Muse 的基本操作。

在 Emacs 中按快捷鍵 Ctrl+x Ctrl+f ,創建文件 ~/Documents/wiki/FirstPage.muse ,輸入如清單3所示的內容:


清單3 FirstPage.muse
                  #title 第一個Wiki頁面    * 一級標題需要一個星號開頭  ** 二級標題需要兩個星號開頭  *** 三級標題需要三個星號開頭      段落需要兩個以上空行              居中一行文字需要以6個以上的空白開頭  ----  示一個橫線只需要輸入4個以上的“-”標記    這是 *著重* 的文字,這是 **進一步著重** 的文字,這是 ***更進一步的著重*** 的文字    這是 _下劃線_ 文字,這是 =等寬verbatim and monospace= 的文字    *** 列表:      - 無序列表需要以空格和“-”開頭    1. 有序列表需要以空格和數字序號開頭    字典 :: 名詞定義需要以“::”分隔名詞和所定義文字    - 列表也可以嵌套       1. 列表嵌套深度按照開頭空格的多少來控制       2. 可以繼續嵌套不同類型的列表          - 比如這樣    *** 表格:  表格標題 || 用“||”分割  表格內容	| 用“|”分割  表格結尾	||| 用“|||”分割  

在 FirstPage.muse 文件輸入過程中,Emacs 的 Muse 模式會根據用戶的輸入,生成不同的顯示預覽,如圖1所示,這樣大大方便了我們寫 wiki 的效率,在 Emacs 中實現了所見即所得的用戶體驗。


圖 1. Emacs 的 Muse 模式

輸入完成後,按快捷鍵 Ctrl+c Ctrl+p ,該快捷鍵用來在當前工程目錄下生成 wiki 網頁。生成成功后, wiki 網頁位於 ~/Documents/wiki/publish/FirstPage.html 。按快捷鍵 Ctrl+c Ctrl+v 來預覽該網頁,如圖2所示:


圖 2. 第一份 wiki 網頁

這樣我們就生成了一份 wiki 網頁。在 firstPage.muse 文件中,我們用各種標記符號(*, -, =)來表示網頁中的各種元素(標題,加粗,列表),這樣就非常簡單地生成了一張 wiki 網頁,它可以發布到網站中直接供人閱讀,非常適用於記錄技術文檔和筆記。

更為重要的是,Emacs Muse 不僅可以由 wiki 記號生成 HTML 格式,還可以生成 Latex, texinfo, docbook 等等多種格式,這也意味著我們完全可以用 Emacs Muse 來製作各種格式的文檔。Emacs Muse 對多種文檔格式的支持非常豐富,這在它的官方網站上可以找到完整的支持文檔列表。





自定義單元測試報告的樣式和自動分析結果

上面內容簡單介紹了 Emacs Muse 的基本用法和基本快捷鍵。由於 Emacs 天生的易於擴展的特點,Emacs Muse 也提供了大量的函數介面來擴展它的功能。擴展 Emacs 所用的 Elisp 語言簡潔優美,非常容易學習和編程。

Muse 默認生成的 HTML 格式是非常普通的網頁樣式,我們可以通過自定義其樣式來美化其輸出。我們可以根據項目,工作和學習的具體需要,來定義不同需求的格式,使其成為一個多樣式的網頁生成工具。下面本文就介紹如何自定義一種簡單的單元測試報告的格式,該格式基於 HTML 的輸出樣式,但自定義了表單樣式,同時根據測試結果來生成統計數據。

將 Muse 擴展代碼放在 emacs-muse.el 文件中,在 .emacs 文件最後一樣加入代碼來包括這個文件,如清單4所示,把載入 muse 包的代碼以及自定義樣式的代碼放入到 emacs-muse.el 文件,這樣可以方便編寫調試,而且還能方便在命令行調用。


清單4 在.emacs文件中包括Muse擴展包載入代碼
                  ;; Emacs Muse      (load-file "~/emacs-muse.el")  

自定義單元測試樣式

Muse 提供了函數 muse-define-style 來自定義格式,還有函數 muse-derive-style 來繼承已定義的格式。本文所需輸出的測試結果是一種自定義的 HTML 格式,所以只需要函數 muse-derive-style 來繼承自 HTML 格式即可,代碼如清單5所示,這裡我們定義了一個名為 UT 的新格式,它繼承自 HTML 格式。


清單5 定義UT樣式
                  (muse-derive-style "ut" "html"  				   :header 'ut-html-header  				   :style-sheet 'ut-style-sheet)  

在該格式中,HTML 文件頭由函數 ut-html-header 定義,該函數代碼如清單6所示:


清單6 ut-html-header函數定義HTML文件頭
                  (setq ut-html-header  "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">  <html>    <head>      <title><lisp>    (concat (muse-publishing-directive \"title\")            (let ((author (muse-publishing-directive \"author\")))              (if (not (string= author (user-full-name)))                  (concat \" (by \" author \")\"))))  </lisp></title>      <meta name=\"generator\" content=\"muse.el\">      <meta http-equiv=\"<lisp>muse-html-meta-http-equiv</lisp>\"            content=\"<lisp>muse-html-meta-content-type</lisp>\">      <lisp>        (let ((maintainer (muse-style-element :maintainer)))          (when maintainer            (concat \"<link rev=\\\"made\\\" href=\\\"\" maintainer \"\\\">\")))  </lisp>  <lisp>(muse-style-element :style-sheet muse-publishing-current-style) </lisp>    </head>    <body>      <h1><lisp>(muse-publishing-directive \"title\")</lisp></h1>  	<p><big><em><lisp>(let ((author (muse-publishing-directive \"author\")))              (if (not (string= author (user-full-name)))                  (concat \"by \" author )))</lisp></em></big></p>  	<p><big><em><lisp>(let ((date (muse-publishing-directive \"date\")))                   (concat \"Last Modified: \" date ))</lisp></em></big></p>      <h2><lisp>(let ((package (muse-publishing-directive \"package\")))                   (concat \"Test script Package &mdash\; \" package )) </lisp> </h2>     <table class=\"muse-table\" border=\"2\" cellpadding=\"5\">     <tbody><tr><td><span class=\"pass\">PASS</span></td>  <td>Passed all test</td></tr><tr><td><span class=\"fail\">FAIL</span></td>  <td>Failed for new issue</td></tr><tr><td><span class=\"attempt\">ATTEMPTED</span></td>  <td>Tried but there is known issue</td></tr>  <tr><td><span class=\"nattempt\">NOT ATTEMPTED</span></td>   <td>Not tried</td></tr></tbody></table>  <!-- Page published by Emacs Muse begins here -->\n")  

清單6中,定義了 UT 樣式中所輸出的網頁文件的開頭部分代碼。作為一個簡單的單元測試結果報告樣式,在該網頁的開始部分,說明了報告的標題,測試人員名稱,單元測試的代碼包。定義了四種測試結果: PASS, FAIL, ATTEMPTED, NOT ATTEMPTED ,分別表示通過,失敗,有已知錯誤但已運行了單元測試,未測試。這段報告的開頭部分所對應的輸出網頁位置如圖4 所示。

為了表示不同樣式元素,我們需要有個自定義的樣式表嵌入到輸出網頁中,清單5 的代碼中,樣式表格式由函數 ut-style-sheet 定義,該函數定義如清單7所示。


清單7 ut-style-sheet函數定義樣式表
                  (setq ut-style-sheet  	  "<style type=\"text/css\">  body {    FONT: 14px/1.4 'Trebuchet MS',Verdana, Arial, Helvetica, sans-serif;   background:#fff;   width: 60em;   margin: 0 auto 0;   padding: 2em 0 6em 0;   text-align: left;  }  a {    font-family: Verdana;   text-decoration:none;   font-weight:bold;   color:#c00;  }  a:hover {   background:#000000;   color:#FFFFFF;  }  h1 a { color:#666;}  h2 a { color:#666;}  h3 a { color:#666;}  h4 a { color:#666;}  h1 {  font-size: 40px;   color:#666;   border-bottom: 5px solid #000;   padding: 2px;   margin: 0px;   margin-bottom: 8px;  }  h2 {    color:#666;   font-size: 22px;   padding: 2px;   margin-top: 15px;   border-bottom: 2px solid #000000;  }  h3 {    color:#666;   font-size: 18px;   padding: 2px;   margin-top: 5px;  }  h4 {    color:#666;   font-size: 18px;   padding: 2px;   margin-top: 5px;  }  img {      float: right;      margin: 10px;      border-style:solid; border-width:2px;  }  #im {     clear: right;}  pre {      border: #777777 1px solid;      padding: 0.5em;      margin-left: 1em;      margin-right: 2em;      white-space: pre;      background-color: #e6e6e6;      color: black;  }  .pass {  color:Green;  }  .fail {  color:Red;  font-weight: bold; }  .attempt {  color:Maroon;  font-weight: bold; }  .nattempt {  color:Silver;   }  .verse {      white-space: pre;      margin-left: 1em;  }  dt {      font-weight: bold;}  li {     margin-bottom: 0.9ex;}  blockquote {       margin-left: 2em;       color: #4444ff;  }  td {  font-size: 13px;}  th {    background: #d6d6d6;    font-size: 14px;  }   </style>")  

在清單7所示的樣式表中,我們定義了網頁報告中的各種元素(標題,章節,表格等)的格式。而且還專門針對於單元測試結果報告,定義了四種樣式: .pass, .fail, .attempt, .nattempt 。定義了它們的顏色和字體,讀者可以根據自己的需要,修改它們的樣式。

這樣我們做好了一份測試報告的準備工作,定義了不同測試結果的 html 樣式,定義了報告開始部分的格式。下面將介紹如何生成報告的主體部分。

自定義單元測試報告內容格式

在 Muse 中我們可以使用一種格式類似於 XML 的標籤來表示特定的內容,例如如果想輸入一段包括了 Muse 的關鍵字字元的文本,而又不想被 Muse 所解釋這些關鍵字字元,則可以在 Muse 文件中輸入如清單8所示的文本:


清單8 標籤示例
                  <verbatim>  這是 *著重* 的文字,這是 **進一步著重** 的文字,這是 ***更進一步的著重*** 的文字  </verbatim>  

輸出則如圖3所示。


圖 3. verbatim 標籤輸出示例

Muse 提供了多種標籤可以在 Muse 文件中使用,包括 lisp(動態嵌入 lisp 代碼的運行結果),python (動態嵌入 python 代碼的運算結果), src (對標籤內的代碼文本進行著色)等等。通過 Muse 函數 muse-publish-markup-tags ,我們可以自定義標籤。本測試報告自定義了 result 標籤,通過在該標籤範圍內輸入測試結果, 那麼Muse 在生成 HTML 文件時,會根據我們的擴展代碼解釋 result 標籤內的內容,生成我們所期望的格式。result 標籤的定義代碼如清單9所示。


清單9 result標籤定義代碼
                  (defvar muse-pass-tag '("pass" t nil nil muse-ut-pass-tag))  (defun muse-ut-pass-tag (beg end)    (delete-region beg end)    (goto-char beg)    (muse-insert-markup "<span class=\"pass\">PASS</span>"))    (defvar muse-fail-tag '("fail" t nil nil muse-ut-fail-tag))  (defun muse-ut-fail-tag (beg end)    (delete-region beg end)    (goto-char beg)    (muse-insert-markup "<span class=\"fail\">FAIL</span>"))    (defvar muse-attempt-tag '("attempt" t nil nil muse-ut-attempt-tag))  (defun muse-ut-attempt-tag (beg end)    (delete-region beg end)    (goto-char beg)    (muse-insert-markup "<span class=\"attempt\">ATTEMPTED</span>"))    (defvar muse-nattempt-tag '("nattempt" t nil nil muse-ut-nattempt-tag))  (defun muse-ut-nattempt-tag (beg end)    (delete-region beg end)    (goto-char beg)    (muse-insert-markup "<span class=\"nattempt\">NOT ATTEMPTED</span>"))    (defvar muse-result-tag '("result" t t nil muse-ut-result-tag))  (defun muse-ut-result-tag (beg end attrs)    "Insert unit test result     <result> ...  </result>."    (muse-publish-markup-attribute beg end attrs nil  	(save-excursion        (save-restriction      		(setq passed 0)  		(setq failed 0)  		(setq attempted 0)  		(setq nattempted 0)  		(goto-char (point-min))  		(while (re-search-forward "<pass/>" nil t)  			  (setq passed (1+ passed)))  		(goto-char (point-min))  		(while (re-search-forward "<fail/>" nil t)  			  (setq failed (1+ failed)))  		(goto-char (point-min))  		(while (re-search-forward "<attempt/>" nil t)  			  (setq attempted (1+ attempted)))  		(goto-char (point-min))  		(while (re-search-forward "<nattempt/>" nil t)  			  (setq nattempted (1+ nattempted)))  		(goto-char (point-min))  		(setq count (+ passed failed attempted nattempted))  		  		(goto-char (point-min))  		(muse-insert-markup (concat "<h3>Result:</h3><p><strong><em>"   				"Totally " (number-to-string count) " cases,"   				(number-to-string passed) " passed, "   				(number-to-string failed) " failed, "   				(number-to-string attempted) " attempted, "   				(number-to-string nattempted) " not attempted."   				"</em></strong></p>"))  ))))  (add-to-list 'muse-publish-markup-tags muse-result-tag)  (add-to-list 'muse-publish-markup-tags muse-pass-tag)  (add-to-list 'muse-publish-markup-tags muse-fail-tag)  (add-to-list 'muse-publish-markup-tags muse-attempt-tag)  (add-to-list 'muse-publish-markup-tags muse-nattempt-tag)  

在清單9中,首先我們定義了四個單元測試結果標籤,這四個標籤分別代表了四種單元測試結果,並對每種結果應用對用的樣式表樣式,進行著色和設置字體。然後定義了 result 標籤,該標籤統計在該標籤內容中所包含的每種測試結果標籤的個數。最後一句代碼將 result 標籤和四種單元測試結果標籤發布到 muse 的標籤列表中。

解釋 result 標籤的代碼位於 muse-ut-result-tag 函數中,它首先定義了4個變數用於存儲每種測試結果的次數,然後不斷遍歷標籤中的文本,統計測試結果標籤的個數來獲知測試結果。最後,該函數輸出統計結果,將其列在報告中的 Result 小節的開始處,如圖4 所示。

生成第一份單元測試結果報告

上面做好了所有的準備工作,保存好 emacs-muse.el 文件。重啟 Emacs 或者運行命令 M-x eval-buffer ,我們自定義的單元測試報告格式就生效了。

現在新建一個 Muse 工程,如清單10所示:


清單10 第一個單元測試報告工程
                  ;添加一個wiki工程  (setq muse-project-alist        '(("MyWiki"           ("~/Documents/wiki" :default "index")           (:base "html" :path "~/Document/wiki/publish"))   	("MyUTReport"           ("~/Documents/wiki2" :default "index")           (:base "ut" :path "~/Document/wiki2/publish"))))  

新建 muse 源文件 ~/Documents/wiki2/firstReport.muse ,輸入如清單11所示的文本。


清單11 第一份單元測試報告的Muse文件
                  #author sky  #package org.example    <result>  Script Name || Result || Description  Script_a || <fail/> || resaon...reason...reason...reason...  Scrpit_b | <pass/> |   Script_c | <nattempt/> | why...why...why...why...why...why...why...  Script_d | <attempt/> | result...result...result...result  </result>    * Analysis    1. Below methods need refactor:  <src lang="c">  1. code ...  2. code2...  </src>  

按快捷鍵 Ctrl+c Ctrl+p 發布工程,發布成功后,按快捷鍵 Ctrl+c Ctrl+v 來預覽結果,結果圖4 所示。


圖 4. 第一份測試報告輸出結果





同其他工具的結合

通過 Emacs Muse ,我們可以通過簡單的標記來生成精美的測試結果報告。生成報告所需要的muse文件既可以是手動輸入,也可以是由自動化測試工具來自動生成。通過 Emacs 的 batch 模式,我們可以從命令行運行 Emacs ,讓它以命令行的形式執行 emacs-muse.el 文件中的 Elisp 代碼,生成 HTML 格式的網頁報告。這一切只需要執行如下的命令:

skys-imac:~ sky$ emacs –q -batch  -l ~/emacs-muse.el –f muse-project-batch-publish MyWiki  

最後的 MyWiki 是 muse 工程的名字。這樣,通過自動化的測試工具來生成 muse 文件,再從命令行運行生成 HTML 報告。這樣就將 Emacs Muse 同其他工具完美結合在一起。而且可以根據自己需求來自定義樣式,將藝術和技術完美地結合到了一起,達到了很好的效果。





結束語

Emacs Muse 擴展性強,並在發布 Wiki 方面有著獨到的強大功能。它支持格式多,支持源代碼標記,可嵌套列表等等。有興趣的讀者可以直接訪問附錄中 Muse 的官方網站 http://mwolson.org/ ,這個網站完全使用 Emacs Muse 生成併發布到網路中的,並且所有的 Muse 文件都是開放代碼,可以直接下載學習的。正是由於它的強大擴展性,也使得我們可以自定義樣式來生成符合我們要求的文檔,這也正是 Emacs 編輯器的迷人之處。

(責任編輯:A6)



[火星人 ] 用 Emacs Muse 來製作測試結果報告已經有579次圍觀

http://coctec.com/docs/linux/show-post-69167.html