4

エンジニアリング分析の出力を確認するために単体テストを作成しようとしています。特定の有効数字までの分析に対してチェックしたい理論値があります。たとえば、次のようになります。

Ixx_ther = 0.000123
Iyy_ther = 0.0123

Ixx, Iyy = getI(*args, **kwargs)

self.assertAlmostEqual(Ixx_ther, Ixx, 6)
self.assertAlmostEqual(Iyy_ther, Iyy, 4)

この場合、どちらの場合も許容範囲を 6 に設定するとテストが厳しくなり、4 に設定すると緩すぎるため、チェックしようとしている数を知る必要があります。私が必要としているのは、同じ有効数字数と等しいかどうかのテストです。理想的なのは、次のように言うことです。

Ixx_ther = 1.23E-4
Iyy_ther = 1.23E-2

Ixx, Iyy = getI(*args, **kwargs)

self.assertAlmostEqual(Ixx_ther, Ixx, 2)
self.assertAlmostEqual(Iyy_ther, Iyy, 2)

assert ステートメントで指数を削除し、有意桁のみが等しいかどうかをチェックします。これは以前に行われたと思いますが、この方法で同等性を主張する組み込み関数を見つけることができませんでした。誰もが前にこの問題を抱えていましたか、

質問

1) 誰かが以前にこの問題を抱えていて、エンジニアリング分析のための単体テストの一般的なガイドを知っていますか?

2) 組み込みのソリューションはありますか。この問題に

3) 誰かがこの方法で機能するカスタム assert ステートメントを既にプログラムしていますか?

4

4 に答える 4

4

Re:これに対する組み込みの解決策はありますか:numpy依存関係として持つことができる場合は、 numpy.testingを見てください。

assert_allcloseここに例があります(ドキュメントからの逐語的):

>>> x = [1e-5, 1e-3, 1e-1]
>>> y = np.arccos(np.cos(x))
>>> assert_allclose(x, y, rtol=1e-5, atol=0)

編集:完全を期すために、ソースコードへのリンクを次に示します:assert_allclose実際の作業をnp.allcloseに転送します。これは、@Mark Ransomの回答とほぼ同じです(さらに、配列引数と無限大の処理)。

于 2013-10-30T17:01:48.520 に答える
0

素晴らしいアイデアをありがとうroippi、私はあなたのコードを多少修正しました:

def assertAlmostEqualSigFig(self, arg1,arg2,tolerance=2):
    if tolerance > 1: 
        tolerance -= 1
    #end

    str_formatter = '{0:.' + str(tolerance) + 'e}'
    significand_1 = float(str_formatter.format(arg1).split('e')[0])
    significand_2 = float(str_formatter.format(arg2).split('e')[0])

    exponent_1 = int(str_formatter.format(arg1).split('e')[1])
    exponent_2 = int(str_formatter.format(arg2).split('e')[1])

    self.assertEqual(significand_1, significand_2)
    self.assertEqual(exponent_1, exponent_2)

    return

私はいくつかのことを変更しました

1) 仮数だけでなく指数もチェックします (それは一番の引き出しワードですね)

2)仮数と指数をそれぞれ float / int に変換します。これは必要ないかもしれませんが、文字列ではなく数値として数値の等価性をチェックする方が快適です。

3) Jim Lewis0.0123 の適切なフォーマット文字列 {0:.3e} は 0.123E-1 ではなく 1.230E-2 であるため、公差を 1 ずつ調整する必要があることに注意してください。つまり、3 つの有効数字が必要な場合は、小数点の前の桁も有効であるため、小数点以下の 2 桁のみが必要です。

Hers は実装例です

class testSigFigs(Parent_test_class):

    @unittest.expectedFailure
    def test_unequal_same_exp(self):
        self.assertAlmostEqualSigFig(0.123, 0.321, 3)

    @unittest.expectedFailure
    def test_unequal_diff_exp(self):
        self.assertAlmostEqualSigFig(0.123, 0.0321, 3)

    @unittest.expectedFailure
    def test_equal_diff_exp(self):
        self.assertAlmostEqualSigFig(0.0123, 0.123, 3)

    def test_equal_same_exp(self):
        self.assertAlmostEqualSigFig(0.123, 0.123, 3)

    def test_equal_within_tolerance(self):
        self.assertAlmostEqualSigFig(0.123, 0.124, 2)
    #end

そして出力:

test_equal_diff_exp (__main__.testSigFigs) ... expected failure
test_equal_same_exp (__main__.testSigFigs) ... ok
test_equal_within_tolerance (__main__.testSigFigs) ... ok
test_unequal_diff_exp (__main__.testSigFigs) ... expected failure
test_unequal_same_exp (__main__.testSigFigs) ... expected failure

----------------------------------------------------------------------
Ran 5 tests in 0.081s

OK (expected failures=3)

お二方、フィードバックありがとうございます。

于 2013-10-29T14:54:50.390 に答える
0

おそらくあなたの質問の全範囲に答えていないかもしれませんが、これは私がそのような関数を書く方法です:

def assertAlmostEqual(arg1,arg2,tolerance=2):
    str_formatter = '{0:.' + str(tolerance) + 'e}'
    lhs = str_formatter.format(arg1).split('e')[0]
    rhs = str_formatter.format(arg2).split('e')[0]
    assert lhs == rhs

Python の文字列書式設定ミニ言語を利用して、フロートを特定の方法で書式設定できます。したがって、私たちができることは、それらを強制的に指数表記でフォーマットすることです。つまり、入力の場合0.123、次の0.000123ようになります。

str_formatter.format(0.123) == '1.23e-01'
str_formatter.format(0.000123) == '1.23e-04'

あとは、指数を切り捨てて等値を主張するだけです。

デモ:

assertAlmostEqual(0.0123,0.0001234)

assertAlmostEqual(0.123,0.0001234)

assertAlmostEqual(0.123,0.0001234,tolerance=3)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
/home/xxx/<ipython-input-83-02fbd71b2e87> in <module>()
----> 1 assertAlmostEqual(0.123,0.0001234,tolerance=3)

/home/xxx/<ipython-input-74-ae32ed74769d> in assertAlmostEqual(arg1, arg2, tolerance)
      3     lhs = str_formatter.format(arg1).split('e')[0]
      4     rhs = str_formatter.format(arg2).split('e')[0]
----> 5     assert lhs == rhs
      6 

AssertionError: 

私が定義した方法が気に入らない場合は、オフバイワンの問題が発生する可能性がありますtolerance。しかし、アイデアを理解します。

于 2013-10-28T20:26:46.953 に答える