             let range = NSRange(location: location, length: length)
             let replacement = String("ab\nc".prefix(Int.random(in: 0...4)).shuffled())
             
-            lineString.string = lineString.string.replacingCharacters(in: range, with: replacement) as NSString
-            lineString.invalidateLineRanges(in: NSRange(location: range.location, length: replacement.length),
-                                            changeInLength: replacement.length - range.length)
+            lineString.replaceCharacters(in: range, with: replacement)
             
             for index in (0..<lineString.string.length).shuffled() {
                 XCTAssertEqual(lineString.lineNumber(at: index), lineString.string.lineNumber(at: index),

        XCTAssertEqual(lineString.lineRange(at: 4), NSRange(4..<5))  // "\n"
        XCTAssertEqual(lineString.lineRange(at: 5), NSRange(5..<11))  // " cat \n"
        
        lineString.string = lineString.string.replacingCharacters(in: NSRange(1..<2), with: "") as NSString  // 1st " "
        lineString.invalidateLineRanges(in: NSRange(1..<1), changeInLength: -1)
        XCTAssertEqual(lineString.string, "d\n\n\n cat \n ")
        XCTAssertEqual(lineString.lineNumber(at: 1), 1)
        XCTAssertEqual(lineString.lineRange(at: 1), NSRange(0..<2))  // "d\n"

        let lineString2 = LineString("dog \n\n cat \n cow ")
        XCTAssertEqual(lineString2.lineNumber(at: 17), 4)
        
        for _ in 0..<20 {
            let string = String(" 🐶 \n 🐱 \n 🐮 \n".shuffled())
            let lineString = LineString(string)
            
