2012-10-06 31 views
0

所以我參加了一個Perl編程課,我們的老師給了我們第一個任務,很少談論如何真正編程perl。這就是我們的老師分配的:Perl自動化文件測試

「你應該寫一個腳本(你可以命名你的腳本,只要你認爲合適),它接受3個文件名作爲參數,第一個文件名對應於用C++編寫的程序源代碼。 filename對應於C++程序要使用的輸入文件,第一個文件名列爲C++程序第三個文件名對應於一個文本文件,該文件包含所需程序的預期正確輸出可以提供目錄路徑的文件名。

如果程序不要求輸入文件,在命令行上的第二個參數應的文件名「的/ dev /空」。

所有文件 - 程序源文件,輸入文件和預期輸出文件 - 應在腳本使用它們之前複製到臨時測試目錄中,以避免原始文件被修改測試程序。如果暫存目錄不存在,您的腳本應該創建一個作爲當前工作目錄的子目錄。

然後,您的腳本應該使用GNU g ++編譯器編譯並鏈接源代碼的臨時副本。然後腳本應該運行該程序 - 將輸出保存到臨時文件中存儲在暫存測試目錄中。

運行該程序後,腳本應使用UNIX命令diff將上一步中生成的實際輸出與預期的輸出文件進行比較,並報告輸出是否符合規範或報告由diff程序。

完成後,您的腳本應刪除所有臨時副本和暫存文件。不要刪除原來的程序,原始輸入文件,原來的預期輸出文件或暫存目錄本身」

我有這個至今:

#!/usr/bin/perl -w 

use strict; 

my ($line, $program, $input, $output); 

print "Give the program, input, and standart output for testing. "; 

$line = <>; 
chomp $line; 

($program, $input, $output) = split/\s+/, $line; # split/\s+/ is to separate spaces from the input 

my($o_test) = $output + "_test"; 

print "$program "; 
print "$input "; 
print "$output "; 

system("mkdir test_scratch") == 0 
or die "failed to create test_scratch. exiting...." 

system("cp $program, /test_scratch/"); # error 
system("cp $input, /test_scratch/"); 
system("cp $output, /test_scratch/"); 

system("cd test_scratch"); 

system("g++ $program"); 
system("chmod +x a.out"); 

system("./a.out < $input > $o_test"); 

my($DIFF) = system("diff $output $o_test") # error 

if[ $DIFF != ""] 
    print ("Output conforms to specifications."); # error 
then 
    print ("$DIFF"); 
system("cd .."); 

我在#收到錯誤我甚至不知道如何做「/ dev/null」,我花了很多時間在網上查找東西並搜索stackoverflow,但我只是不知道該怎麼辦。這是一個非常長的問題,但我不知道還有什麼可以做的。謝謝你的任何幫助,你可以給我

+2

你有沒有試過問你的老師? – choroba

+0

我傾向於與科洛巴,這似乎是一個「通過他們進入火災」類型的任務。另外,我希望你的教授比大型系統調用更深入Perl編程,Perl比BASH腳本的替代更有用。 –

回答

0

我收到錯誤#代碼中。

這個錯誤的簡單解決方法是刪除逗號。標準Linux cp命令不會在源和目標之間使用逗號。你也可以考慮File::Copy在Perl中複製文件。

我甚至不知道如何去做「/ dev/null」。

/dev/null是標準的Linux文件(*),它指向空白。您可以將字節寫入此文件,然後它們消失。你可以嘗試從這個文件中讀取字節,並且什麼也沒有。

這使你有兩個選擇:

  1. 只需直接使用/ dev/null的,程序將無法讀取空字節流什麼。
  2. 檢查是否輸入文件是等於的/ dev/null,則並且不給C++程序的輸入值,如果輸入是/ dev/null的。

這兩種方法都可行。如果將/ dev/null複製到某個目錄,則會得到一個名爲'null'的新零長度文件,這對C++程序來說是一個完全有效的空輸入文件。

(*)不,如果您來自Windows世界,/ dev/null不是您習慣的文件。它不存在於磁盤上 - 永遠不會,永遠也不會。但是傳統的Unix理念是將每個數據源都作爲一個文件,即使該文件不存在於磁盤上。例如,請參閱Linux/proc文件系統,該文件系統允許您在目錄樹結構中查看有關CPU,進程等的信息。直到socket API採取了完全不同的路線之後,這種哲學纔有所緩解。如果你正在尋找一個操作系統,它使基本一切到一個文件中,包括網絡連接,並在屏幕上,仰望Plan 9。不過,我不會推薦在Plan 9上做家庭作業,並期望他們能夠在Linux上工作。


N.B.不要忘記檢查來自system的返回碼,因爲如果g ++無法編譯C++程序,將無法運行不存在的編譯程序。

0

有幾個模塊,它可以幫助你在這裏。我建議的第一個是ExtUtils::CBuilder,它可以爲你管理一個構建過程。然後,您也可以使用File::Copy將東西移動到臨時文件夾中,甚至使用File::chdir來管理工作目錄。由於prof指定您應該使用diff,但您可能應該使用diff模塊,但您可以使用Test::More來檢查輸出是否符合預期。


只是以供將來參考,這是我將如何完成類似的任務(不保留臨時目錄,不需要diff):

#!/usr/bin/env perl 

use strict; 
use warnings; 

use File::chdir; 
use File::Temp; 
use File::Copy; 
use File::Basename; 
use File::Slurp; 

use ExtUtils::CBuilder; 
use Test::More tests => 1; 

die "Not enough inputs\n" unless @ARGV >= 3; 

# create a temporary directory 
my $temp = File::Temp->newdir; 

# copy all arguments to that temporary directory 
copy $_, $temp for @ARGV; 

# store only the filename (not path) of each argument 
my ($cpp_file, $in_file, $expected_file) = map { scalar basename $_ } @ARGV; 

# change working directory to temporary one (via File::chdir) 
local $CWD = $temp; 

# build the executable 
my $builder = ExtUtils::CBuilder->new(config => {cc => 'g++'}); 

my $obj = $builder->compile(source => $cpp_file, 'C++' => 1); 
my $exe = $builder->link_executable(objects => 'hello.o'); 

# run the executable 
my $output = `./$exe $in_file`; 

# read in the expected file 
my $expected = read_file $expected_file; 

# test the resulting output 
is $output, $expected, 'Got expected output from executable'; 

請注意,您可能需要小心輸出和預期文件換行符。