Birim Testleri

Kodu değiştirdikten veya ekledikten sonra mevcut birim testlerini çalıştırmalı ve daha fazla test yapmalısınız. Tüm testler, kodun sıkıştırılmamış sürümlerinde yürütülür.

İki grup birim testi vardır: JS testleri ve blok oluşturucu testleri.

JS Testleri

JS testleri, Blockly'nin çekirdeğindeki dahili JavaScript işlevlerinin çalışmasını onaylar. Birim testleri çalıştırmak için Mocha'yı, bağımlılıkları belirlemek için Sinon'ı ve kod hakkında iddialarda bulunmak için Chai'yi kullanırız.

Testleri Çalıştırma

npm run test, hem blok hem de blok halinde örneklerde birim testlerini çalıştırır. Blok halinde bu işlem, hata ayıklama ve derleme gibi diğer testleri de çalıştırır. Tüm mocha testlerini etkileşimli olarak çalıştırmak için tests/mocha/index.html uygulamasını bir tarayıcıda da açabilirsiniz.

Yazma Testleri

Test çalıştırmak için Mocha TDD arayüzünü kullanıyoruz. Testler paketler halinde düzenlenir. Bu paketlerde hem ek alt paketler hem de/veya testler bulunabilir. Genel olarak, Blockly'nin her bileşeni (toolbox veya workspace gibi), bir veya daha fazla paket içeren kendi test dosyasına sahiptir. Her paket, ilgili paketteki her testten önce ve sonra çağrılacak bir setup ve teardown yöntemine sahip olabilir.

Test Yardımcıları

Test yazarken yararlı olabilecek, Blockly'ye özel bir dizi yardımcı işlevimiz vardır. Bunları core (çekirdek) ve blockly-samples (blok örnekler) bulabilirsiniz.

Yardımcı işlevler arasında, testlerinizden önce ve sonra çağrılması gerekli olan sharedTestSetup ve sharedTestTeardown yer alır (Şartlar bölümüne bakın).

sharedTestSetup:
  • Sinon sahte zamanlayıcılar kurar (bazı testlerde this.clock.runAll kullanmanız gerekir).
  • Blokly.Events.fire dosyasını hemen etkinleşecek şekilde değiştirir (yapılandırılabilir).
  • defineBlocksWithJsonArray ile tanımlanan blockType öğelerinin otomatik olarak temizlenmesini ayarlar.
  • this bağlamında erişilebilir olması amaçlanan birkaç özellik tanımlar:
    • this.clock (ancak geri yüklenmemelidir), aksi takdirde sharedTestTeardown içinde sorunlara neden olur.
    • this.eventsFireStub
    • this.sharedCleanup (addMessageToCleanup ve addBlockTypeToCleanup ile kullanılır) (NOT: Bloğu defineBlocksWithJsonArray ile tanımladıysanız addBlockTypeToCleanup kullanmanıza gerek yoktur)

İşlev, kurulumu yapılandırmak için isteğe bağlı bir options parametresine sahiptir. Şu anda yalnızca Blockly.Events.fire öğesinin hemen tetiklenmesi için saplamanın gerekip gerekmediğini belirlemek için kullanılmaktadır (varsayılan olarak koparılır).

sharedTestTeardown:
  • this.workspace çalışma alanını ortadan kaldırır (tanımlandığı yere bağlı olarak, daha fazla bilgi için Test Gereksinimleri bölümüne bakın).
  • Tüm artıkları geri yükler.
  • defineBlocksWithJsonArray ve addBlockTypeToCleanup aracılığıyla eklenen tüm engelleme türlerini temizler.
  • addMessageToCleanup kullanılarak eklenen tüm iletileri temizler.

Test Koşulları

  • Her test, en dış paketin kurulumunda ilk satır olarak sharedTestSetup.call(this);, bir dosya için en dış paketin sökümündeki son satır olarak da sharedTestTeardown.call(this); çağırmalıdır.
  • Genel bir araç kutusuna sahip bir çalışma alanına ihtiyacınız varsa testteki index.html hazır ayar araç kutularından birini kullanabilirsiniz. Aşağıda konuyla ilgili bir örnek verilmiştir.
  • this.workspace ürününü uygun şekilde imha etmeniz gerekir. Çoğu testte, en dış pakette this.workspace tanımlarsınız ve bunu sonraki tüm testler için kullanırsınız ancak bazı durumlarda bunu iç bir pakette tanımlayabilir veya yeniden tanımlayabilirsiniz (örneğin, testlerinizden biri, başlangıçta kurduğunuzdan farklı seçeneklere sahip bir çalışma alanı gerektirir). Testin sonunda atılmalıdır.
    • En dış pakette this.workspace öğesini tanımlar ve hiçbir zaman yeniden tanımlamazsanız başka bir işlem yapmanız gerekmez. sharedTestTeardown tarafından otomatik olarak imha edilecek.
    • this.workspace öğesini bir iç pakette ilk kez tanımlarsanız (yani en dıştaki pakette tanımlamadıysanız) paketin sökümü sırasında workspaceTeardown.call(this, this.workspace) yöntemini çağırarak manuel olarak ortadan kaldırmanız gerekir.
    • En dış pakette this.workpace tanımlar ancak daha sonra bunu iç test paketinde yeniden tanımlarsanız üst düzey pakette tanımlanan orijinal çalışma alanını sökmek için yeniden tanımlamadan önce workspaceTeardown.call(this, this.workspace) yöntemini çağırmanız gerekir. Ayrıca, bu iç paketin ayrıştırılmasında tekrar workspaceTeardown.call(this, this.workspace) çağrısı yaparak yeni değeri manuel olarak ortadan kaldırmanız gerekir.

Test Yapısı

Birim testleri genellikle düzenleme, harekete geçme, onaylama şeklinde özetlenebilen bir dizi yapıyı izler.

  1. Düzenle: Test edilen davranış için dünyanın durumunu ve gerekli koşulları ayarlayın.
  2. İşlem yap: Test edilen davranışı tetiklemek için test edilen kodu çağırın.
  3. İddia: Doğruluğu doğrulamak için döndürülen değer veya sahte nesnelerle etkileşimler hakkında iddialarda bulunun.

Basit bir testte düzenlenecek herhangi bir davranış bulunmayabilir ve eylem ve iddia aşamaları, iddiadaki test edilen koda yapılan çağrının satır içine alınmasıyla birleştirilebilir. Daha karmaşık durumlarda bu 3 aşamayı takip ederseniz testleriniz daha okunabilir olacaktır.

Aşağıda örnek bir test dosyası verilmiştir (gerçekten basitleştirilmiştir).

suite('Flyout', function() {
  setup(function() {
    sharedTestSetup.call(this);
    this.toolboxXml = document.getElementById('toolbox-simple');
    this.workspace = Blockly.inject('blocklyDiv',
        {
          toolbox: this.toolboxXml
        });
  });

  teardown(function() {
    sharedTestTeardown.call(this);
  });

  suite('simple flyout', function() {
    setup(function() {
      this.flyout = this.workspace.getFlyout();
    });
    test('y is always 0', function() {
      // Act and assert stages combined for simple test case
      chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout is 0');
    });
    test('x is right of workspace if flyout at right', function() {
      // Arrange
      sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
        viewWidth: 100,
      });
      this.flyout.targetWorkspace.toolboxPosition = Blockly.TOOLBOX_AT_RIGHT;
      this.flyout.toolboxPosition_ = Blockly.TOOLBOX_AT_RIGHT;

      // Act
      var x = this.flyout.getX();

      // Assert
      chai.assert.equal(x, 100, 'x is right of workspace');
    });
  });
});

Bu örnekte dikkate alınması gereken noktalar:

  • Bir paket, ek setup ve teardown yöntemlerine sahip diğer süitler içerebilir.
  • Her paket ve testin açıklayıcı bir adı vardır.
  • Chai onaylamaları, kod hakkında iddialarda bulunmak için kullanılır.
    • Test başarısız olursa gösterilecek isteğe bağlı bir dize bağımsız değişkeni sağlayabilirsiniz. Bu, bozuk testlerde hata ayıklamayı kolaylaştırır.
    • Parametrelerin sırası chai.assert.equal(actualValue, expectedValue, optionalMessage) şeklindedir. actual ve expected değerlerini değiştirirseniz hata mesajları anlamlı olmaz.
  • Sinon, gerçek kodu çağırmak istemediğinizde yöntemler belirlemek için kullanılır. Bu örnekte, bu testle alakalı olmadığından gerçek metrikler işlevini çağırmak istemeyiz. Yalnızca sonuçların test edilen yöntem tarafından nasıl kullanıldığıyla ilgileniriz. Sinon, test onaylarımızda kolayca kontrol edebileceğimiz bir hazır yanıt döndürmek için getMetrics işlevini saptırır.
  • Her bir paketin setup yöntemleri, yalnızca tüm testler için geçerli olan genel kurulum içermelidir. Belirli bir davranışa yönelik test belirli bir koşula dayanıyorsa bu koşul ilgili testte açıkça belirtilmelidir.

Hata Ayıklama Testleri

  • Testleri bir tarayıcıda açabilir ve geliştirici araçlarını kullanarak ayrılma noktaları belirleyebilir ve testlerinizin beklenmedik bir şekilde başarısız olup olmadığını (veya beklenmedik şekilde başarısız olup olmadığını) inceleyebilirsiniz.
  • Bir testte veya pakette .only() veya .skip() ayarlayarak yalnızca söz konusu test grubunu çalıştırın ya da testi atlayın. Örneğin:

    suite.only('Workspace', function () {
      suite('updateToolbox', function () {
        test('test name', function () {
          // ...
        });
        test.skip('test I don’t care about', function () {
          // ...
        });
      });
    });
    

    Kodunuzu kaydetmeden önce bunları kaldırmayı unutmayın.

Blok Oluşturucu Testleri

Her blokun kendi birim testleri vardır. Bu testler, blokların beklendiği gibi işlevlerden kod oluşturduğunu doğrular.

  1. Firefox veya Safari'de tests/generators/index.html eklentisini yükleyin. Chrome ve Opera'nın, testlerin yerel "file://" sisteminden yüklenmesini engelleyen güvenlik kısıtlamaları olduğunu (Sorunlar 41024 ve 47416) unutmayın.
  2. Açılır menüden sistemdeki test edilecek ilgili bölümü seçin ve "Yükle"yi tıklayın. Engellemeler, çalışma alanında görünecektir.
  3. "JavaScript"i tıklayın.
    Oluşturulan kodu kopyalayıp bir JavaScript konsolunda çalıştırın. Çıkış "Tamam" ile bitiyorsa test geçmiş demektir.
  4. "Python"u tıklayın.
    Oluşturulan kodu kopyalayıp bir Python yorumlayıcıda çalıştırın. Çıkış "OK" ile bitiyorsa test geçilmiştir.
  5. "PHP"yi tıklayın.
    Oluşturulan kodu kopyalayıp bir PHP yorumlayıcıda çalıştırın. Çıkış "OK" ile bitiyorsa test geçilmiştir.
  6. "Lua"yı tıklayın.
    Oluşturulan kodu kopyalayıp bir Lua commenter'da çalıştırın. Çıkış "OK" ile bitiyorsa test geçilmiştir.
  7. "Dart"ı tıklayın.
    Oluşturulan kodu kopyalayıp bir Dart yorumlayıcıda çalıştırın. Çıkış "OK" ile bitiyorsa test geçilmiştir.

Blok Oluşturma Testlerini Düzenleme

  1. tests/generators/index.html uygulamasını bir tarayıcıda yükleyin.
  2. Açılır menüden sistemin ilgili bölümünü seçin ve "Yükle"yi tıklayın. Engellemeler, çalışma alanında görünecektir.
  3. Bloklarda değişiklik veya ekleme yapın.
  4. "XML"i tıklayın.
  5. Oluşturulan XML dosyasını tests/generators/ ürünündeki uygun dosyaya kopyalayın.