functional tdd with f
play

Functional TDD with F# Mark Seemann http://blog.ploeh.dk @ploeh - PowerPoint PPT Presentation

Look, no Mocks! Functional TDD with F# Mark Seemann http://blog.ploeh.dk @ploeh TDD is dead! http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html Is TDD dead? A system you cant test Detestable


  1. Look, no Mocks! Functional TDD with F# Mark Seemann http://blog.ploeh.dk @ploeh

  2. TDD is dead! http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html

  3. Is TDD dead?

  4. A system you can’t test

  5. Detestable http://martinfowler.com/bliki/Detestable.html

  6. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden);

  7. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation

  8. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation {

  9. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate,

  10. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name,

  11. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email,

  12. public IHttpActionResult Post(ReservationRendition rendition) { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity

  13. { DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity });

  14. DateTimeOffset requestedDate; if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity }); ctx.SaveChanges();

  15. if (!DateTimeOffset.TryParse(rendition.Date, out requestedDate)) return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity }); ctx.SaveChanges(); }

  16. return this.BadRequest("Invalid date."); var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity }); ctx.SaveChanges(); }

  17. var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity }); ctx.SaveChanges(); } return this.Ok();

  18. var min = requestedDate.Date; var max = requestedDate.Date.AddDays(1); using (var ctx = new ReservationsContext()) { var reservedSeats = (from r in ctx.Reservations where min <= r.Date && r.Date < max select r.Quantity) .DefaultIfEmpty(0) .Sum(); if (rendition.Quantity + reservedSeats > capacity) return this.StatusCode(HttpStatusCode.Forbidden); ctx.Reservations.Add(new Reservation { Date = requestedDate, Name = rendition.Name, Email = rendition.Email, Quantity = rendition.Quantity }); ctx.SaveChanges(); } return this.Ok(); }

  19. Test-Induced Damage

  20. public IHttpActionResult Post(ReservationRendition rendition) { if (!this.apiValidator.Validate(rendition)) return this.BadRequest("Invalid date."); var r = this.mapper.Map(rendition); var reservedSeats = this.repository.GetReservedSeats(r.Date); if (!this.maîtreD.CanAccept(rendition.Quantity, reservedSeats)) return this.StatusCode(HttpStatusCode.Forbidden); this.repository.Save(r); return this.Ok(); } }

  21. public interface IApiValidator { bool Validate(ReservationRendition rendition); } public interface IReservationMapper { Reservation Map(ReservationRendition rendition); } public interface IReservationRepository { int GetReservedSeats(DateTimeOffset date); void Save(Reservation reservation); } public interface IMaîtreD { bool CanAccept(int requestedSeats, int reservedSeats); }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend