Birim Testleri

Kodu değiştirdikten veya ekledikten sonra mevcut birim testlerini çalıştırmalı ve daha fazla test yazmayı düşünmelisiniz. 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 temelindeki dahili JavaScript işlevlerinin çalışmasını onaylar. Birim testleri çalıştırmak için Mocha, bağımlılıkları stub yapmak için Sinon ve kod hakkında iddialarda bulunmak için Chai'yi kullanırız.

Testleri çalıştırma

Hem blockly hem de blockly-samples'de npm run test birim testlerini çalıştırır. Blok halinde, bu işlemde linting ve derleme gibi diğer testler de yürütülür. Tüm mocha testlerini etkileşimli olarak çalıştırmak için tests/mocha/index.html dosyasını bir tarayıcıda da açabilirsiniz.

Yazma Testleri

Testleri çalıştırmak için Mocha TDD arayüzünü kullanırız. Testler, hem ek alt süitler hem de/veya testler içerebilen süitler halinde düzenlenir. Genellikle Blockly'nin her bileşeninin (toolbox veya workspace gibi) bir veya daha fazla paket içeren kendi test dosyası vardır. Her pakette, paketteki her testten önce ve sonra sırasıyla çağrılacak bir setup ve teardown yöntemi bulunabilir.

Test Yardımcıları

Test yazarken faydalı olabilecek, Blockly'ye özgü çeşitli yardımcı işlevlerimiz vardır. Bu dosyaları core ve blockly-samples klasörlerinde bulabilirsiniz.

Yardımcı işlevler, testlerinizden önce ve sonra çağrılması gerekli olan sharedTestSetup ve sharedTestTeardown değerlerini içerir (Gereksinimler bölümüne bakın).

sharedTestSetup:
  • Sinon sahte zamanlayıcılar ayarlar (bazı testlerde this.clock.runAll kullanmanız gerekir).
  • Blockly.Events.fire işlevini hemen tetiklemek için stub oluşturur (yapılandırılabilir).
  • defineBlocksWithJsonArray aracılığıyla tanımlanan blockTypes için otomatik temizleme işlemini ayarlar.
  • this bağlamında erişilebilir olması amaçlanan birkaç mülkü tanımlar:
    • this.clock (ancak geri yüklenmemesi şurada sorunlara neden olur: sharedTestTeardown)
    • this.eventsFireStub
    • this.sharedCleanup (addMessageToCleanup ve addBlockTypeToCleanup ile birlikte kullanılır) (NOT: defineBlocksWithJsonArray kullanarak bloğu tanımladıysanız addBlockTypeToCleanup kullanmanız gerekmez)

İşlev, kurulumu yapılandırmak için isteğe bağlı bir options parametresine sahiptir. Şu anda yalnızca Blockly.Events.fire'ün hemen tetiklenmesi için stub'lanıp lanmayacağını belirlemek için kullanılır (varsayılan olarak stub'lanır).

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

Test Şartları

  • Her test, en dıştaki paketin kurulumundaki ilk satır olarak sharedTestSetup.call(this); ve bir dosya için en dıştaki paketin yıkımındaki son satır olarak sharedTestTeardown.call(this); çağrısı yapmalıdır.
  • Genel bir araç kutusu içeren bir çalışma alanına ihtiyacınız varsa testteki önceden ayarlanmış araç kutularından birini kullanabilirsiniz index.html. Aşağıda konuyla ilgili bir örnek verilmiştir.
  • this.workspace adlı cihazı uygun şekilde atmalısınız. Çoğu testte this.workspace değerini en dıştaki pakette tanımlar ve sonraki tüm testler için kullanırsınız ancak bazı durumlarda bunu bir iç pakette tanımlayabilir veya yeniden tanımlayabilirsiniz (örneğin, testlerinizden biri için başlangıçta ayarladığınızdan farklı seçeneklere sahip bir çalışma alanı gerekir). Testin sonunda imha edilmelidir.
    • this.workspace öğesini en dış pakette tanımlar ve hiçbir zaman yeniden tanımlamazsanız başka bir işlem yapmanız gerekmez. sharedTestTeardown tarafından otomatik olarak imha edilecektir.
    • this.workspace öğesini ilk kez bir iç pakette tanımlarsanız (yani en dış pakette tanımlamadıysanız) söz konusu paketin teardown işlevinde workspaceTeardown.call(this, this.workspace)'i çağırarak öğeyi manuel olarak kaldırmanız gerekir.
    • this.workpace öğesini en dıştaki pakette tanımlarsanız ancak daha sonra bir iç test paketinde yeniden tanımlarsanız üst düzey pakette tanımlanan orijinal çalışma alanını kaldırmak için önce workspaceTeardown.call(this, this.workspace) öğesini yeniden tanımlamadan önce çağırmanız gerekir. Ayrıca, bu iç paketin yıkımında workspaceTeardown.call(this, this.workspace)'yi tekrar çağırarak yeni değeri manuel olarak da imha etmeniz gerekir.

Test Yapısı

Birim testleri genellikle düzenle, hareket et, iddia et şeklinde özetlenebilir belirli bir yapıya uyar.

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

Basit bir testte düzenlenecek bir davranış olmayabilir. Ayrıca, işleme ve iddia aşamaları, test edilen koda yapılan çağrıyı iddiaya dahil ederek birleştirilebilir. Bu 3 aşamaya bağlı kalırsanız daha karmaşık durumlarda testleriniz daha okunaklı olur.

Burada, örnek bir test dosyasını görebilirsiniz (gerçek dosyadan 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 dikkat edilmesi gereken noktalar:

  • Bir paket, ek setup ve teardown yöntemlerine sahip diğer paketleri içerebilir.
  • Her paket ve testin açıklayıcı bir adı vardır.
  • Chai iddiaları, 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 sayede, bozuk testlerde hata ayıklama işlemini kolayca yapabilirsiniz.
    • Parametrelerin sırası chai.assert.equal(actualValue, expectedValue, optionalMessage). actual ve expected değerlerini değiştirirseniz hata mesajları anlamlı olmaz.
  • Gerçek kodu çağırmak istemediğinizde Sinon, yöntemlerin yerine geçmek için kullanılır. Bu örnekte, gerçek metrikler işlevi bu testle alakalı olmadığı için çağrılmak istenmez. Yalnızca sonuçların test edilen yöntem tarafından nasıl kullanıldığı önemlidir. Sinon, test onaylarımızda kolayca kontrol edebileceğimiz hazır bir yanıt döndürmek için getMetrics işlevini saplıyor.
  • Her paketin setup yöntemleri yalnızca tüm testler için geçerli olan genel kurulumu içermelidir. Belirli bir davranışla ilgili bir 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çıp ayrılma noktaları belirlemek ve testlerinizin beklenmedik bir şekilde başarısız olup olmadığını (veya beklenmedik bir şekilde geçip geçmediğini) araştırmak için geliştirici araçlarını kullanabilirsiniz.
  • Yalnızca belirli bir test grubunu çalıştırmak için bir test veya pakette .only() veya .skip() değerini ayarlayı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 bloğun kendi birim testleri vardır. Bu testler, blokların istendiği gibi işleyen kod oluşturduğunu doğrular.

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

Blok Oluşturucu Testlerini Düzenleme

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