質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

PHPUnit

PHPUnitは、PHP向けのユニット・テスト向けフレームワークで、手動では手間のかかるテスト作業を自動化し、繰り返し実行することが可能です。

Q&A

解決済

2回答

4136閲覧

引数不足の例外を捕捉できない

hotta

総合スコア1613

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

PHPUnit

PHPUnitは、PHP向けのユニット・テスト向けフレームワークで、手動では手間のかかるテスト作業を自動化し、繰り返し実行することが可能です。

0グッド

1クリップ

投稿2017/06/13 01:20

編集2017/06/13 05:53

my_add_return_int() という(自作の PHP Extension の中にある)関数
のテストを行っています。正常系は通りますが、引数が足りない場合の例外を
捕捉できません。

bash

1vagrant:~/php/ext/my_ext$ cat /usr/local/lib/php.ini 2extension=/home/vagrant/php/ext/my_ext/modules/my_ext.so 3

php

1vagrant:~/php/ext/my_ext$ cat tests/MyAddReturnIntTest.php 2<?php 3 4use PHPUnit\Framework\TestCase; 5 6class MyAddReturnIntTest extends TestCase 7{ 8 public function test3plus4returns7() 9 { 10 $ret = my_add_return_int(3, 4); 11 $this->assertEquals(7, $ret); 12 } 13 14 /** 15 * @expectedException InvalidArgumentException 16 */ 17 public function testLackOfParameter() 18 { 19 $ret = my_add_return_int(3); 20 } 21} 22

bash

1vagrant:~/php/ext/my_ext$ php -v 2PHP 7.1.5 (cli) (built: Jun 7 2017 09:13:29) ( NTS DEBUG ) 3Copyright (c) 1997-2017 The PHP Group 4Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies 5 6vagrant:~/php/ext/my_ext$ phpunit tests/MyAddReturnIntTest.php 7PHPUnit 6.2.1 by Sebastian Bergmann and contributors. 8 9.E 2 / 2 (100%) 10 11Time: 133 ms, Memory: 10.00MB 12 13There was 1 error: 14 151) MyAddReturnIntTest::testLackOfParameter 16Wrong parameter count for my_add_return_int() 17 18/usr/local/src/php-7.1.5/ext/my_ext/tests/MyAddReturnIntTest.php:18 19 20ERRORS! 21Tests: 2, Assertions: 1, Errors: 1. 22 23

@expectedException を
$this->expectException(InvalidArgumentException::class);
に書き換えても同じエラーでした。試しに error_reporting() を入れてみると

php

1 /** 2 * @expectedException InvalidArgumentException 3 */ 4 public function testLackOfParameter() 5 { 6 error_reporting(E_ERROR); 7 $this->expectException(InvalidArgumentException::class); 8 $ret = my_add_return_int(3); 9 } 10

bash

11) MyAddReturnIntTest::testLackOfParameter 2Failed asserting that exception of type "InvalidArgumentException" is thrown. 3

となります。

無理やり RuntimeException に変換すれば補足できるのですが、PHPUnit のドキュメントの
記述と齟齬がある気がして、今ひとつ納得がいきません。ご教示をお願いします。

php

1<?php 2 3use PHPUnit\Framework\TestCase; 4 5class MyAddReturnIntTest extends TestCase 6{ 7 public static function setUpBeforeClass() { 8 set_error_handler(function($errno, $errstr, $errfile, $errline) { 9 throw new RuntimeException($errstr . " on line " 10 . $errline . " in file " . $errfile); 11 }); 12 } 13 14 /** 15 * @expectedException RuntimeException 16 */ 17 public function testLackOfParameter() 18 { 19 error_reporting(E_ERROR); 20 $ret = my_add_return_int(3); 21 } 22} 23

bash

1vagrant:~/php/ext/my_ext$ phpunit tests/MyAddReturnIntTest.php 2PHPUnit 6.2.1 by Sebastian Bergmann and contributors. 3 4.. 2 / 2 (100%) 5 6Time: 122 ms, Memory: 10.00MB 7 8OK (2 tests, 2 assertions) 9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

引数不足はE_WARNINGを返すので捕まえたければ以下のような感じでしょうか?

PHP

1set_error_handler('myErrorHandler'); 2function myErrorHandler($errno, $errstr, $errfile, $errline) 3{ 4 switch($errno) { 5 case E_WARNING: 6 throw new exception("I got warning:".$errstr."<br>"); 7 break; 8 case E_USER_WARNING: 9 throw new exception("My warning:".$errstr."<br>"); 10 break; 11 default: 12 return false; 13 } 14 return true; 15} 16 17try{ 18 print test(10); 19}catch(exception $e){ 20 print $e->getMessage(); 21} 22 23function test($a,$b){ 24 return $a*$b; 25}

エラーが発生する前に事前にテストをする場合は
call_user_func_arrayなどで引数を渡すように変更し
(new ReflectionFunction("test"))->getNumberOfParameters()のようにして
必要な引数の数を数えておく手もあります。

もちろんエラーを出したくないだけであれば引数に初期値を与えておくだけでもいいでしょう

PHP

1function test($a=0,$b=0){ 2 return $a*$b; 3} 4print test(100);//エラーにならない 5

投稿2017/06/13 02:02

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hotta

2017/06/13 05:42

質問の趣旨としては、このようなケースに対応できるような、 PHPUnit のテストケースを書きたいということでした。 http://php.net/manual/ja/language.errors.php7.php ちなみに PHP7 からエラーの扱いが変わっており、ご提示いただいた コードだと、以下のようになるようです。 Fatal error: Uncaught ArgumentCountError: Too few arguments to function test(), 1 passed in /home/vagrant/temp/e.php on line 23 and exactly 2 expected in /home/vagrant/temp/e.php:28 Stack trace: #0 /home/vagrant/temp/e.php(23): test(10) #1 {main} thrown in /home/vagrant/temp/e.php on line 28
yambejp

2017/06/13 05:50

それは失礼しました PHP7は互換の絡みがあって導入していませんでした 追加でお知らせできそうなことがあればまた追記するようにします
guest

0

自己解決

【自己解決しました】
PHPUnit だけではできなかったのですが、
https://github.com/VladaHejda/PhpUnitAssertException
というのを見つけました。これを入れて、テストコードを以下のようにしたら通りました。

php

1<?php 2 3use PHPUnit\Framework\TestCase; 4require_once '/home/vagrant/PhpUnitAssertException/src/AssertException.php'; 5 6function my_app_takes_two_args(int $a, int $b): int { 7 return $a + $b; 8} 9 10class MyAddReturnIntTest extends TestCase 11{ 12 use VladaHejda\AssertException; 13 14 public function testLackOfParameter() 15 { 16 $test = function () { 17 my_app_takes_two_args(3); 18 }; 19 20 $this->assertError($test, ArgumentCountError::class); 21 } 22} 23

注意事項として、当該 trait は mbstring に依存します。mbstring が入ってないと、

bash

1Error: Call to undefined function mb_strpos()

というエラーになりました。

投稿2017/06/13 05:53

編集2017/06/13 06:44
hotta

総合スコア1613

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hotta

2017/06/13 07:22

スミマセン。まだ不完全でした。 php で定義された関数であれば、上記の方法でうまく捕獲できます。 ただ本来の質問である、「PHP Extension 内で定義された関数」だと、返ってくるエラーのレベルが異なるようです。 ためしに、上記のテストで "strlen()" など C レベルで定義されている関数を指定した場合、"Failed asserting the class of a Throwable..." となります。もう少し調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問