如何比较RSpec中的两个哈希值?

时间:2016-03-07 18:24:21

标签: ruby rspec

我有两个哈希h1h2,我想在RSpec中进行比较。

我想检查一些转换后h1的元素是否与h2相同,我们称之为f。也就是说,我想验证k中的每个键h1h1[k] == f(h2[k])

例如,如果h2中的所有值都是h1中相应值的两倍,那么我想检查h1中每个键k的值,{{ 1}}。

在RSpec中执行此操作的正确方法是什么?目前我这样做:

h2[k] == h1[k] * 2

但这似乎很笨拙。

6 个答案:

答案 0 :(得分:5)

听起来你正在测试的是转型。我会考虑写这样的东西:

expected: {:k1=>2, :k2=>4}
     got: {:k1=>1, :k2=>4}

(compared using ==)

Diff:
@@ -1,3 +1,3 @@
-:k1 => 2,
+:k1 => 1,
 :k2 => 4,

对我来说,描述清楚地说明了我们的期望。然后我可以很容易地从测试中看到输入是什么和预期的输出。此外,这会利用哈希匹配器,它将在失败时为两个哈希提供一个很好的差异:

public class ButtonControler {

    Activity mActivity;

    public ButtonControler(Activity activity) {
        mActivity = activity;
    }

    public void buttonPressed() {
        //add the buttons contorls
        //if the top button is pushed get the promotion page
        final ImageButton promo = (ImageButton) mActivity.findViewById(R.id.apivita);
        promo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent getPromos = new Intent(v.getContext(), PromotionMain.class);
                mActivity.startActivity(getPromos);
            }
        });
        //if the button 1  is pushed get the defulat webview page
        final ImageButton button1 = (ImageButton) mActivity.findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("Button1: ", "Pressed");
                Intent button1Pressed = new Intent(v.getContext(), MyWebViewMain.class);
                mActivity.startActivity(button1Pressed);
            }
        });


        //if the cart is pushed get the cart webview page
        final ImageButton cart = (ImageButton) mActivity.findViewById(R.id.button2);
        cart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("Cart: ", "Pressed");
                Intent myCart = new Intent(v.getContext(), Cart.class);
                mActivity.startActivity(myCart);
            }
        });

        //if the button 3  is pushed get the defulat webview page
        final ImageButton button3 = (ImageButton) mActivity.findViewById(R.id.button3);
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("Button3: ", "Pressed");
                Intent buttonPressed = new Intent(v.getContext(), MyWebViewMain.class);
                mActivity.startActivity(buttonPressed);
            }
        });

        //if the button 4  is pushed get the defulat webview page
        final ImageButton button4 = (ImageButton) mActivity.findViewById(R.id.button4);
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("Button4: ", "Pressed");
                Intent buttonPressed = new Intent(v.getContext(), MyWebViewMain.class);
                mActivity.startActivity(buttonPressed);
            }
        });

        //if the Store list  is pushed get the defulat webview page
        final ImageButton storeList = (ImageButton) mActivity.findViewById(R.id.button5);
        storeList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("StoreList: ", "Pressed");
                Intent myStoreList = new Intent(v.getContext(), StoreList.class);
                mActivity.startActivity(myStoreList);
            }
        });

        //if the Store list  is pushed get the notification
        final Button notification = (Button) mActivity.findViewById(R.id.gcmlogo);
        notification.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("Notificatiion: ", "Pressed");
                Intent myNotification = new Intent(v.getContext(), GCMMainActivity.class);
                mActivity.startActivity(myNotification);
            }
        });

        //if the Store list  is pushed get the notification
        final Button myPage = (Button) mActivity.findViewById(R.id.mypage);
        myPage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("MyPage: ", "Pressed");
                //read the stored values
                String storedUser = CustomerPerferences.readString(mActivity.getApplicationContext(), CustomerPerferences.USER_NAME, "");
                String storedPass = CustomerPerferences.readString(mActivity.getApplicationContext(), CustomerPerferences.PASSWORD, "");
                //see if use has entered a username and password
                if (storedUser.equals("USER_NAME")) {
                    Log.d("Loging in", "Go!");
                    Intent goToLogin = new Intent(v.getContext(), LoginPage.class);
                    mActivity.startActivity(goToLogin);
                } else {

                    Intent goToLogin = new Intent(v.getContext(), CustomerPage.class);
                    goToLogin.putExtra("user_name", storedUser);
                    mActivity.startActivity(goToLogin);
                }

            }
        });


    }
}

虽然我会质疑键值关系的含义。这些只是您试图通过的测试用例吗?如果是这样,我只会让每个人都进行独特的测试。如果还有更多内容,那么我可能会质疑为什么变换方法没有提供哈希开始。

答案 1 :(得分:1)

h1.each do |k, v|
  expect(v).to eq(f(h2[k]))
end

至于我,它似乎更具可读性。

答案 2 :(得分:1)

怎么样:

h2 = f(h1)

expect(h2.keys).to eq(h1.keys)  # I assume you want this, too

h1.keys.each do |k|
  expect(h2[k]).to eq(h1[k] * 2) 
end

多一点啰嗦,但也许更具可读性?

答案 3 :(得分:1)

我们在 RSpecs 中使用 hashdiff 来处理这个问题。

我们开发了一个自定义匹配器:

RSpec::Matchers.define :match_hash do |expected|
  match do |actual|
    Hashdiff.best_diff(expected, actual).blank?
  end
  failure_message do |actual|
    "expected that #{actual} would match #{expected}, but it has these differences: #{Hashdiff.best_diff(expected, actual)}"
  end
end

我们像这样使用它:expect(actual_hash).to match_hash(expected_hash)

答案 4 :(得分:0)

为了完全平等:

expect(h1).to eq h2.map { |k, v| [k, f(v)] }.to_h

答案 5 :(得分:0)

如果有人要为嵌套大哈希寻找更好的差异,我想出了这一点:

import sympy as sp
sp.var("a, b, c, d, z")
myeq = sp.Eq(c * sp.sin(a * (b / 2 - z)) + d * sp.cos(a * (b / 2 - z)), 0)
sol = sp.solve(myeq, z)
print(sol)

Output: [(a*b - 4*atan((c - sqrt(c**2 + d**2))/d))/(2*a), (a*b - 4*atan((c + sqrt(c**2 + d**2))/d))/(2*a)]

原始要点:https://gist.github.com/fabriciofreitag/b7458725ffef08eaf5ea541c95385a92

输出示例: enter image description here