Gözlemlenebilir Dizileri Test Etme ve Hata Ayıklama
Rx uygulamanızı test etme
Uzun bir süre boyunca değerleri yayımlayan gözlemlenebilir bir diziniz varsa, bunu gerçek zamanlı olarak test etme bir esnetme olabilir. Reactive Extension kitaplığı, zaman geçirmeyi beklemeden bu tür bir kodu test etmeye yardımcı olmak için TestScheduler türünü sağlar. TestScheduler VirtualScheduler'ı devralır ve öykünülmüş zamanda diziler oluşturmanıza, yayımlamanıza ve dizilere abone olmanıza olanak tanır. Örneğin, doğru ölçeği korurken 2 dakikalık bir çalıştırmada tamamlanması 5 gün süren bir yayını sıkıştırabilirsiniz. Ayrıca geçmişte gerçekleşen bir diziyi (örneğin, bir önceki yıla ait hisse senedi değer akışları dizisi) alabilir ve yeni değerleri gerçek zamanlı olarak dışarı itiyormuş gibi hesaplayabilir veya abone olabilirsiniz.
Start fabrika yöntemi, kuyruk boş olana kadar tüm zamanlanmış görevleri yürütür veya kuyruğa alınan görevlerin yalnızca belirtilen saate kadar yürütülmesi için bir süre belirtebilirsiniz.
Aşağıdaki örnek, belirtilen OnNext bildirimleriyle çalışırken gözlemlenebilir bir sıra oluşturur. Ardından test zamanlayıcısını başlatır ve sık erişimli gözlemlenebilir diziye ne zaman abone olunup atılacaklarını belirtir. Start yöntemi, listedeki tüm bildirimleri kaydeden bir Messages özelliğini içeren ITestableObserver örneğini döndürür.
Sıra tamamlandıktan sonra, Messages özelliğini karşılaştırmak için ReactiveAssert.AreElementEqual yöntemini ve beklenen değerlerin listesini kullanarak her ikisinin de özdeş olup olmadığını (aynı sayıda öğeyle ve öğelerin eşit ve aynı sırada) olup olmadığını görürüz. Bunu yaparak, beklediğimiz bildirimleri aldığımızı doğrulayabiliriz. Örneğimizde, abone olma işlemini yalnızca 150'de başlattığımız için değerini abc
kaçıracağız. Ancak şu ana kadar 400'de aldığımız değerleri karşılaştırdığımızda, aslında diziye abone olduktan sonra yayımlanan tüm değerleri aldığımızı fark ederiz. Ayrıca bildirimin OnCompleted
doğru zamanda 500'de tetiklendiğini de doğrularız. Ayrıca, abonelik bilgileri CreateHotObservable yöntemi tarafından döndürülen ITestableObservable türü tarafından da yakalanır.
Aynı şekilde ReactiveAssert.AreElementsEqual kullanarak aboneliklerin gerçekten beklenen zamanlarda gerçekleştiğini onaylayabilirsiniz.
using System;
using System.Reactive;
using System.Reactive.Linq;
using Microsoft.Reactive.Testing;
class Program : ReactiveTest
{
static void Main(string[] args)
{
var scheduler = new TestScheduler();
var input = scheduler.CreateHotObservable(
OnNext(100, "abc"),
OnNext(200, "def"),
OnNext(250, "ghi"),
OnNext(300, "pqr"),
OnNext(450, "xyz"),
OnCompleted<string>(500)
);
var results = scheduler.Start(
() => input.Buffer(() => input.Throttle(TimeSpan.FromTicks(100), scheduler))
.Select(b => string.Join(",", b)),
created: 50,
subscribed: 150,
disposed: 600);
ReactiveAssert.AreElementsEqual(results.Messages, new Recorded<Notification<string>>[] {
OnNext(400, "def,ghi,pqr"),
OnNext(500, "xyz"),
OnCompleted<string>(500)
});
ReactiveAssert.AreElementsEqual(input.Subscriptions, new Subscription[] {
Subscribe(150, 500),
Subscribe(150, 400),
Subscribe(400, 500)
});
}
}
Rx uygulamanızda hata ayıklama
Rx uygulamanızda hata ayıklamak için Do işlecini kullanabilirsiniz. Do işleci, gözlemlenebilir dizideki her öğe için gerçekleştirilecek çeşitli eylemleri belirtmenize olanak tanır (örneğin, öğeyi yazdırma veya günlüğe kaydetme vb.). Bu özellikle birçok işleci zincirlerken ve her düzeyde hangi değerlerin üretildiğini bilmek istediğinizde yararlıdır.
Aşağıdaki örnekte, her saniye tamsayılar oluşturan Buffer örneğini, her birini 5 öğeyi barındırabilecek arabelleklere yerleştirerek yeniden kullanacağız. LINQ Operators kullanarak Gözlemlenebilir Dizileri Sorgulama konu başlığındaki özgün örneğimizde, arabellek dolu olduğunda (ve boşaltılmadan önce) yalnızca son Gözlemlenebilir (IList<>) dizisine abone olacağız. Ancak bu örnekte, do işlecini kullanarak değerleri özgün dizi (saniyede bir tamsayı) tarafından gönderildiğinde yazdıracağız. Arabellek dolduğunda, tüm bunları gözlemcinin abone olması için son sıra olarak teslim etmeden önce durumu yazdırmak için Do işlecini kullanırız.
var seq1 = Observable.Interval(TimeSpan.FromSeconds(1))
.Do(x => Console.WriteLine(x.ToString()))
.Buffer(5)
.Do(x => Console.WriteLine("buffer is full"))
.Subscribe(x => Console.WriteLine("Sum of the buffer is " + x.Sum()));
Console.ReadKey();
Bu örnekte görebileceğiniz gibi, zincirlenmiş gözlemlenebilir diziler dizisinin alıcı ucunda bir abonelik vardır. İlk olarak, Interval işlecini kullanarak saniyeye göre ayrılmış gözlemlenebilir bir tamsayı dizisi oluşturuyoruz. Ardından Buffer işlecini kullanarak arabelleğe 5 öğe yerleştirir ve bunları yalnızca arabellek dolu olduğunda başka bir sıra olarak göndeririz. Son olarak bu, Subscribe işlecine devredilir. Veriler gözlemciye gönderilene kadar tüm bu ara dizileri aşağı yayılım. Aynı şekilde abonelikler de kaynak diziye ters yönde yayılır. Do işlecini bu tür yaymaların ortasına ekleyerek, hata ayıklama gerçekleştirmek için .NET'te Console.WriteLine veya C'de printf() kullandığınız gibi bu tür veri akışında "casusluk" yapabilirsiniz.
Bir öğenin gözlemlenebilir bir dizi tarafından gönderildiği zamanı doğrulamak için Zaman Damgası işlecini de kullanabilirsiniz. Bu, doğruluğu sağlamak için zamana bağlı işlemlerde sorun gidermenize yardımcı olabilir. Kaynak dizi tarafından gönderilen her değerin yayımlandığı zamana kadar eklenmesi için Zaman Damgası işlecini sorguya zincirlediğimiz Oluşturma ve Basit Gözlemlenebilir Sıralara Abone Olma konusunda yer alan aşağıdaki örneği hatırlayın. Bunu yaparak, bu kaynak dizisine abone olduğumuzda hem değerini hem de zaman damgasını alacağız.
Console.WriteLine(“Current Time: “ + DateTime.Now);
var source = Observable.Timer(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1))
.Timestamp();
using (source.Subscribe(x => Console.WriteLine("{0}: {1}", x.Value, x.Timestamp)))
{
Console.WriteLine("Press any key to unsubscribe");
Console.ReadKey();
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
Çıkış şuna benzer olacaktır:
Current Time: 5/31/2011 5:35:08 PM
Press any key to unsubscribe
0: 5/31/2011 5:35:13 PM -07:00
1: 5/31/2011 5:35:14 PM -07:00
2: 5/31/2011 5:35:15 PM -07:00
Timestamp işlecini kullanarak, ilk öğenin gerçekten de diziden 5 saniye sonra dışarı gönderildiğini ve her öğenin 1 saniye sonra yayımlandığını doğruladık.
Ayrıca, hata ayıklamaya yardımcı olmak için lambda ifadelerinin içinde kesme noktaları da ayarlayabilirsiniz. Normalde, yalnızca sorgunun tamamı için belirli bir değeri göstermeden kesme noktası ayarlayabilirsiniz. Bu sınırlamaya geçici bir çözüm olarak sorgunun ortasına Select işlecini ekleyebilir ve kesme noktası ayarlayabilir ve Select deyiminde kendi satırında bir return deyimi kullanarak özdeş değeri kaynağı olarak yansıtabilirsiniz. Ardından deyim satırında bir kesme noktası return
ayarlayabilir ve sorguda ilerlerken değerleri inceleyebilirsiniz.
var seq = Observable.Interval(TimeSpan.FromSeconds(1))
.Do(x => Console.WriteLine(x.ToString()))
.Buffer(5)
.Select(y => {
return y; }) // set a breakpoint at this line
.Do(x => Console.WriteLine("buffer is full"))
.Subscribe(x => Console.WriteLine("Sum of the buffer is " + x.Sum()));
Console.ReadKey();
Bu örnekte kesme noktası satırda return y
ayarlanmıştır. Programda hata ayıkladığınızda, y
değişkeni Yereller penceresinde gösterilir ve toplam sayısını (5)
inceleyebilirsiniz. öğesini genişletirseniz y
, listedeki her öğeyi değeri ve türü de dahil olmak üzere inceleyebilirsiniz.
Alternatif olarak, lambda ifadesini bir deyimi lambda ifadesine dönüştürebilir, deyimin kendi satırında olması için kodu biçimlendirebilir ve sonra bir kesme noktası ayarlayabilirsiniz.
Hata ayıklamayı tamamladıktan sonra tüm Do ve Select çağrılarını kaldırabilirsiniz.
Ayrıca Bkz.
Kavramlar
Basit Gözlemlenebilir Diziler Oluşturma ve Bunlara Abone Olmak
LINQ İşleçlerini Kullanarak Gözlemlenebilir Dizileri Sorgulama
Zamanlayıcıları Kullanma