Aracılığıyla paylaş


C++ DLL'lerini test edin

Bu konuda, C++ için Microsoft Test Framework ile Evrensel Windows Platformu (UWP) uygulamaları için C++ DLL'si için birim testleri oluşturmanın bir yolu açıklanmaktadır. RooterLib DLL, belirli bir sayının karekökünün tahminini hesaplayan bir işlev uygulayarak hesaplamadan kaynaklanan limit teorisinin belirsiz anılarını gösterir. Daha sonra DLL, kullanıcıya matematikle yapılabilecek eğlenceli şeyleri gösteren bir UWP uygulamasına dahil edilebilir.

Bu konu başlığında, geliştirmenin ilk adımı olarak birim testinin nasıl kullanılacağı gösterilmektedir. Bu yaklaşımda, önce test ettiğiniz sistemdeki belirli bir davranışı doğrulayan bir test yöntemi yazarsınız ve ardından testi geçen kodu yazarsınız. Aşağıdaki yordamların sırasına göre değişiklik yaparak, önce test etmek istediğiniz kodu yazmak ve ardından birim testlerini yazmak için bu stratejiyi tersine çevirebilirsiniz.

Bu konu ayrıca, birim testleri ve test etmek istediğiniz DLL için tek bir Visual Studio çözümü ve ayrı projeler oluşturur. Birim testlerini doğrudan DLL projesine de ekleyebilir veya birim testleri ve .DLL için ayrı çözümler oluşturabilirsiniz. Hangi yapının kullanılacağına ilişkin ipuçları için bkz . Mevcut C++ uygulamalarına birim testleri ekleme.

Çözümü ve birim testi projesini oluşturma

Yeni bir test projesi oluşturarak başlayın. Dosya menüsünde Yeni Proje'yi> seçin. Yeni Proje Oluştur iletişim kutusunda, arama kutusuna "test" yazın ve Dil'i C++ olarak ayarlayın. Ardından proje şablonları listesinden Birim Testi Uygulaması (Evrensel Windows) öğesini seçin.

Create a new UWP test project

  1. Yeni Proje iletişim kutusunda Yüklü>Visual C++ öğesini genişletin ve Windows Evrensel'i seçin. Ardından proje şablonları listesinden Birim Testi Uygulaması (Evrensel Windows) öğesini seçin.

  2. Projeyi RooterLibTestsadlandırın; konumu belirtin; çözümü RooterLibadlandırın ve Çözüm için dizin oluştur seçeneğinin işaretli olduğundan emin olun.

    Specify the solution and project name and location

  3. Yeni projede unittest1.cpp dosyasını açın.

    unittest1.cpp

    Şunlara dikkat edin:

    • Her test kullanılarak TEST_METHOD(YourTestName){...}tanımlanır.

      Geleneksel işlev imzası yazmanız gerekmez. İmza, makro TEST_METHOD tarafından oluşturulur. Makro void döndüren bir örnek işlevi oluşturur. Ayrıca test yöntemi hakkında bilgi döndüren statik bir işlev oluşturur. Bu bilgiler, test gezgininin yöntemi bulmasına olanak tanır.

    • Test yöntemleri kullanılarak TEST_CLASS(YourClassName){...}sınıflar halinde gruplandırılır.

      Testler çalıştırıldığında, her test sınıfının bir örneği oluşturulur. Test yöntemleri belirtilmemiş bir sırada çağrılır. Her modül, sınıf veya yöntemden önce ve sonra çağrılan özel yöntemler tanımlayabilirsiniz. Daha fazla bilgi için bkz . Microsoft.VisualStudio.TestTools.CppUnitTestFramework kullanma.

Test Gezgini'nde testlerin çalıştığını doğrulayın

  1. Test kodu ekleyin:

    TEST_METHOD(TestMethod1)
    {
        Assert::AreEqual(1,1);
    }
    

    sınıfının test yöntemlerindeki Assert sonuçları doğrulamak için kullanabileceğiniz birkaç statik yöntem sağladığına dikkat edin.

  2. Test menüsünde Çalıştır'ı ve ardından Tümünü Çalıştır'ı seçin.

    Test projesi derlenip çalışır. Test Gezgini penceresi görüntülenir ve test, Geçirilen Testler altında listelenir. Pencerenin en altındaki Özet bölmesi, seçili testle ilgili ek ayrıntılar sağlar.

    Test Explorer

ÇÖZÜMe DLL projesini ekleme

Çözüm Gezgini'da çözüm adını seçin. Kısayol menüsünde Ekle'yi ve ardından Yeni Proje'yi seçin. Yeni Proje Ekle iletişim kutusunda Dil'i C++ olarak ayarlayın ve arama kutusuna "DLL" yazın. Sonuçlar listesinden Birim Testi Uygulaması (Evrensel Windows - C++/CX) öğesini seçin.

Create the RooterLib project

  1. Yeni Proje Ekle iletişim kutusunda DLL (UWP uygulamaları) öğesini seçin.

  2. RooterLib.h dosyasına aşağıdaki kodu ekleyin:

    // The following ifdef block is the standard way of creating macros which make exporting
    // from a DLL simpler. All files within this DLL are compiled with the ROOTERLIB_EXPORTS
    // symbol defined on the command line. This symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see
    // ROOTERLIB_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef ROOTERLIB_EXPORTS
    #define ROOTERLIB_API  __declspec(dllexport)
    #else
    #define ROOTERLIB_API __declspec(dllimport)
    #endif //ROOTERLIB_EXPORTS
    
    class ROOTERLIB_API CRooterLib {
    public:
        CRooterLib(void);
        double SquareRoot(double v);
    };
    

    Açıklamalar ifdef bloğunu yalnızca dll'nin geliştiricisine değil, projesinde DLL'ye başvuran herkese açıklar. DLL'nin proje özelliklerini kullanarak komut satırına ROOTERLIB_EXPORTS simgesini ekleyebilirsiniz.

    CRooterLib sınıfı bir oluşturucu ve SqareRoot tahmin aracı yöntemini bildirir.

  3. komut satırına ROOTERLIB_EXPORTS simgesini ekleyin.

    1. Çözüm Gezgini'da RooterLib projesini ve ardından kısayol menüsünden Özellikler'i seçin.

      Add a preprocessor symbol definition

    2. RooterLib Özellik Sayfası iletişim kutusunda Yapılandırma Özellikleri'ni genişletin, C++ öğesini genişletin ve Önişlemci'yi seçin.

    3. Önişlemci Tanımları listesinden Düzenle...> öğesini seçin <ve ardından Önişlemci Tanımları iletişim kutusuna ekleyinROOTERLIB_EXPORTS.

  4. Bildirilen işlevlerin en düşük uygulamalarını ekleyin. RooterLib.cpp dosyasını açın ve aşağıdaki kodu ekleyin:

    // constructor
    CRooterLib::CRooterLib()
    {
    }
    
    // Find the square root of a number.
    double CRooterLib::SquareRoot(double v)
    {
        return 0.0;
    }
    
    

Dll işlevlerini test koduna görünür hale getirme

  1. RooterLibTests projesine RooterLib ekleyin.

    1. Çözüm Gezgini'da RooterLibTests projesini ve ardından kısayol menüsünde Başvuru Ekle'yi>seçin.

    2. Başvuru Ekle iletişim kutusunda Projeler'i seçin. Ardından RouterLib öğesini seçin.

  2. RooterLib üst bilgi dosyasını unittest1.cpp dosyasına ekleyin.

    1. unittest1.cpp dosyasını açın.

    2. Bu kodu satırın #include "CppUnitTest.h" altına ekleyin:

      #include "..\RooterLib\RooterLib.h"
      
  3. İçeri aktarılan işlevi kullanan bir test ekleyin. unittest1.cpp'ye aşağıdaki kodu ekleyin:

    TEST_METHOD(BasicTest)
    {
        CRooterLib rooter;
        Assert::AreEqual(
            // Expected value:
            0.0,
            // Actual value:
            rooter.SquareRoot(0.0),
            // Tolerance:
            0.01,
            // Message:
            L"Basic test failed",
            // Line number - used if there is no PDB file:
            LINE_INFO());
    }
    
  4. Çözümü oluşturun.

    Yeni test, Test Gezgini'nde Testleri Çalıştırma düğümünde görünür.

  5. Test Gezgini'nde Tümünü Çalıştır'ı seçin.

    Basic Test passed

    Testi ve kod projelerini ayarladınız ve kod projesinde işlevleri çalıştıran testleri çalıştırabildiğinizi doğruladınız. Artık gerçek testler ve kodlar yazmaya başlayabilirsiniz.

Testleri yinelemeli olarak artırma ve geçmelerini sağlama

  1. Yeni bir test ekleyin:

    TEST_METHOD(RangeTest)
    {
        CRooterLib rooter;
        for (double v = 1e-6; v < 1e6; v = v * 3.2)
        {
            double expected = v;
            double actual = rooter.SquareRoot(v*v);
            double tolerance = expected/1000;
            Assert::AreEqual(expected, actual, tolerance);
        }
    };
    

    İpucu

    Geçen testleri değiştirmemenizi öneririz. Bunun yerine yeni bir test ekleyin, testin geçmesi için kodu güncelleştirin ve sonra başka bir test ekleyin.

    Kullanıcılarınız gereksinimlerini değiştirdiğinde, artık doğru olmayan testleri devre dışı bırakın. Yeni testler yazın ve bunların aynı artımlı şekilde birer birer çalışmasını sağlayın.

  2. Test Gezgini'nde Tümünü Çalıştır'ı seçin.

  3. Test başarısız oluyor.

    The RangeTest fails

    İpucu

    Her testi yazdıktan hemen sonra başarısız olduğunu doğrulayın. Bu, hiçbir zaman başarısız olmayan bir test yazmanın kolay hatasını önlemenize yardımcı olur.

  4. Yeni testin geçmesi için test altındaki kodu geliştirin. RooterLib.cpp dosyasına aşağıdakileri ekleyin:

    #include <math.h>
    ...
    // Find the square root of a number.
    double CRooterLib::SquareRoot(double v)
    {
        double result = v;
        double diff = v;
        while (diff > result/1000)
        {
            double oldResult = result;
            result = result - (result*result - v)/(2*result);
            diff = abs (oldResult - result);
        }
        return result;
    }
    
    
  5. Çözümü derleyin ve Test Gezgini'nde Tümünü Çalıştır'ı seçin.

    Her iki test de geçer.

İpucu

Testleri birer birer ekleyerek kod geliştirin. Tüm testlerin her yinelemeden sonra geçtiğinden emin olun.

Başarısız bir testte hata ayıklama

  1. unittest1.cpp'ye başka bir test ekleyin:

    // Verify that negative inputs throw an exception.
     TEST_METHOD(NegativeRangeTest)
     {
       wchar_t message[200];
       CRooterLib rooter;
       for (double v = -0.1; v > -3.0; v = v - 0.5)
       {
         try
         {
           // Should raise an exception:
           double result = rooter.SquareRoot(v);
    
           swprintf_s(message, L"No exception for input %g", v);
           Assert::Fail(message, LINE_INFO());
         }
         catch (std::out_of_range ex)
         {
           continue; // Correct exception.
         }
         catch (...)
         {
           swprintf_s(message, L"Incorrect exception for %g", v);
           Assert::Fail(message, LINE_INFO());
         }
       }
    };
    
  2. Test Gezgini'nde Tümünü Çalıştır'ı seçin.

    Test başarısız oluyor. Test Gezgini'nde test adını seçin. Başarısız onay vurgulanır. Hata iletisi Test Gezgini'nin ayrıntı bölmesinde görünür.

    NegativeRangeTests failed

  3. Testin neden başarısız olduğunu görmek için işlevin üzerinden geçin:

    1. İşlevin başında SquareRoot bir kesme noktası ayarlayın.

    2. Başarısız testin kısayol menüsünde Seçili Testlerde Hata Ayıkla'yı seçin.

      Çalıştırma kesme noktasında durduğunda kodda adım adım ilerleyin.

    3. Özel durumu yakalamak için RooterLib.cpp dosyasına kod ekleyin:

      #include <stdexcept>
      ...
      double CRooterLib::SquareRoot(double v)
      {
          //Validate the input parameter:
          if (v < 0.0)
          {
            throw std::out_of_range("Can't do square roots of negatives");
          }
      ...
      
      
    4. Test Gezgini'nde, düzeltilen yöntemi test etmek için Tümünü Çalıştır'ı seçin ve bir regresyon getirmediğinizden emin olun.

    Tüm testler artık geçsin.

    All tests pass

Testleri değiştirmeden kodu yeniden düzenleme

  1. İşlevdeki merkezi hesaplamayı basitleştirin SquareRoot :

    // old code
    //result = result - (result*result - v)/(2*result);
    // new code
    result = (result + v/result) / 2.0;
    
  2. Yeniden düzenlenmiş yöntemi test etmek için Tümünü Çalıştır'ı seçin ve bir regresyon getirmediğinizden emin olun.

    İpucu

    Kararlı bir iyi birim testleri kümesi, kodu değiştirdiğinizde hata vermediğinize güven verir.

    Yeniden düzenlemeyi diğer değişikliklerden ayrı tutun.